diff --git a/FSDrivers/IA32/LICENSE.txt b/FSDrivers/IA32/LICENSE.txt new file mode 100644 index 000000000000..cdeae2b89e88 --- /dev/null +++ b/FSDrivers/IA32/LICENSE.txt @@ -0,0 +1,47 @@ +Licensing for the filesystem drivers is complex. Three different licenses +apply to various parts of the code: + +* Christoph Pfisterer's original file system wrapper (FSW) code is covered + by a BSD-style license. Many of the source files with names that take the + form fsw_*.[ch] are so licensed, but this is NOT generally true of + filesystem-specific files (e.g., fsw_ext2.c or fsw_btrfs.c). + +* Certain filesystem drivers are licensed under the GPLv2, either because + they borrow code from the Linux kernel or because a developer (typically + Oracle) applied the GPLv2 license to them. This is true of the ext2fs, + ext4fs, ReiserFS, HFS+, and ISO-9660 drivers. + +* At least one filesystem driver (Btrfs) uses code taken from GRUB, and so + uses the GPLv3 (or later) license. + +Note that the GPLv2 and GPLv3 are, ironically, not compatible licenses. +Thus, code from GPLv2 and GPLv3 projects should not be mixed. The BSD +license used by Pfisterer's original code is compatible with both versions +of the GPL, so the fact that both GPLv2 and GPLv3 drivers is built upon it +is OK. If you intend to contribute to this project's drivers or use the +code yourself, please keep this fact in mind. + +The below was written by Christoph Pfisterer with respect to his original +code: + + File System Wrapper License +============================= + +The various parts of the File System Wrapper source code come from +different sources and may carry different licenses. Here's a quick +account of the situation: + + * The core code was written from scratch and is covered by a + BSD-style license. + + * The EFI host driver was written from scratch, possibly using code + from the TianoCore project and Intel's EFI Application Toolkit. It + is covered by a BSD-style license. + + * The ext2 and reiserfs file system drivers use definitions from the + Linux kernel source. The actual code was written from scratch, + using multiple sources for reference. These drivers are covered by + the GNU GPL. + +For more details, see each file's boilerplate comment. The full text +of the GNU GPL is in the file LICENSE_GPL.txt. diff --git a/FSDrivers/IA32/LICENSE_GPL.txt b/FSDrivers/IA32/LICENSE_GPL.txt new file mode 100644 index 000000000000..d60c31a97a54 --- /dev/null +++ b/FSDrivers/IA32/LICENSE_GPL.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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) + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/FSDrivers/IA32/exfat_ia32.efi b/FSDrivers/IA32/exfat_ia32.efi new file mode 100644 index 000000000000..0ccdf08c247f Binary files /dev/null and b/FSDrivers/IA32/exfat_ia32.efi differ diff --git a/FSDrivers/IA32/ext2_ia32.efi b/FSDrivers/IA32/ext2_ia32.efi new file mode 100644 index 000000000000..a2b14b7cc317 Binary files /dev/null and b/FSDrivers/IA32/ext2_ia32.efi differ diff --git a/FSDrivers/IA32/ext4_ia32.efi b/FSDrivers/IA32/ext4_ia32.efi new file mode 100644 index 000000000000..445b89c9164c Binary files /dev/null and b/FSDrivers/IA32/ext4_ia32.efi differ diff --git a/FSDrivers/IA32/ntfs_ia32.efi b/FSDrivers/IA32/ntfs_ia32.efi new file mode 100644 index 000000000000..0ea083f48fc3 Binary files /dev/null and b/FSDrivers/IA32/ntfs_ia32.efi differ diff --git a/FSDrivers/X64/LICENSE.txt b/FSDrivers/X64/LICENSE.txt new file mode 100644 index 000000000000..cdeae2b89e88 --- /dev/null +++ b/FSDrivers/X64/LICENSE.txt @@ -0,0 +1,47 @@ +Licensing for the filesystem drivers is complex. Three different licenses +apply to various parts of the code: + +* Christoph Pfisterer's original file system wrapper (FSW) code is covered + by a BSD-style license. Many of the source files with names that take the + form fsw_*.[ch] are so licensed, but this is NOT generally true of + filesystem-specific files (e.g., fsw_ext2.c or fsw_btrfs.c). + +* Certain filesystem drivers are licensed under the GPLv2, either because + they borrow code from the Linux kernel or because a developer (typically + Oracle) applied the GPLv2 license to them. This is true of the ext2fs, + ext4fs, ReiserFS, HFS+, and ISO-9660 drivers. + +* At least one filesystem driver (Btrfs) uses code taken from GRUB, and so + uses the GPLv3 (or later) license. + +Note that the GPLv2 and GPLv3 are, ironically, not compatible licenses. +Thus, code from GPLv2 and GPLv3 projects should not be mixed. The BSD +license used by Pfisterer's original code is compatible with both versions +of the GPL, so the fact that both GPLv2 and GPLv3 drivers is built upon it +is OK. If you intend to contribute to this project's drivers or use the +code yourself, please keep this fact in mind. + +The below was written by Christoph Pfisterer with respect to his original +code: + + File System Wrapper License +============================= + +The various parts of the File System Wrapper source code come from +different sources and may carry different licenses. Here's a quick +account of the situation: + + * The core code was written from scratch and is covered by a + BSD-style license. + + * The EFI host driver was written from scratch, possibly using code + from the TianoCore project and Intel's EFI Application Toolkit. It + is covered by a BSD-style license. + + * The ext2 and reiserfs file system drivers use definitions from the + Linux kernel source. The actual code was written from scratch, + using multiple sources for reference. These drivers are covered by + the GNU GPL. + +For more details, see each file's boilerplate comment. The full text +of the GNU GPL is in the file LICENSE_GPL.txt. diff --git a/FSDrivers/X64/LICENSE_GPL.txt b/FSDrivers/X64/LICENSE_GPL.txt new file mode 100644 index 000000000000..d60c31a97a54 --- /dev/null +++ b/FSDrivers/X64/LICENSE_GPL.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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) + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/FSDrivers/X64/exfat_x64.efi b/FSDrivers/X64/exfat_x64.efi new file mode 100644 index 000000000000..214571420d23 Binary files /dev/null and b/FSDrivers/X64/exfat_x64.efi differ diff --git a/FSDrivers/X64/ext2_x64.efi b/FSDrivers/X64/ext2_x64.efi new file mode 100644 index 000000000000..bbb0e1a9c81f Binary files /dev/null and b/FSDrivers/X64/ext2_x64.efi differ diff --git a/FSDrivers/X64/ext4_x64.efi b/FSDrivers/X64/ext4_x64.efi new file mode 100644 index 000000000000..bcb65fc0ffca Binary files /dev/null and b/FSDrivers/X64/ext4_x64.efi differ diff --git a/FSDrivers/X64/ntfs_x64.efi b/FSDrivers/X64/ntfs_x64.efi new file mode 100644 index 000000000000..c7af7ddb844d Binary files /dev/null and b/FSDrivers/X64/ntfs_x64.efi differ diff --git a/FSDrivers/exfat.inf b/FSDrivers/exfat.inf new file mode 100644 index 000000000000..caf940cfda66 --- /dev/null +++ b/FSDrivers/exfat.inf @@ -0,0 +1,27 @@ +# ReadOnly exFAT filesystem driver +# From https://efi.akeo.ie/ v1.5 +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = exfat + FILE_GUID = CB683001-379F-48C7-B7B6-707D29454BF5 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/exfat_x64.efi|* + +[Binaries.IA32] + PE32|IA32/exfat_ia32.efi|* + + diff --git a/FSDrivers/ext2.inf b/FSDrivers/ext2.inf new file mode 100644 index 000000000000..67a985e38515 --- /dev/null +++ b/FSDrivers/ext2.inf @@ -0,0 +1,25 @@ +# EXT2 filesystem driver. See */LICENSE.txt for details. +# https://www.rodsbooks.com/refind/ v0.12 + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ext2 + FILE_GUID = 8EC49C43-D1C4-4E6C-98BF-232CA5D89A1B + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/ext2_x64.efi|* + +[Binaries.IA32] + PE32|IA32/ext2_ia32.efi|* + diff --git a/FSDrivers/ext4.inf b/FSDrivers/ext4.inf new file mode 100644 index 000000000000..c9d0807251cd --- /dev/null +++ b/FSDrivers/ext4.inf @@ -0,0 +1,25 @@ +# EXT4 filesystem driver. See */LICENSE.txt for details. +# https://www.rodsbooks.com/refind/ v0.12 + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ext4 + FILE_GUID = 9d380387-a15a-4053-ae19-ff3495b6d0d5 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/ext4_x64.efi|* + +[Binaries.IA32] + PE32|IA32/ext4_ia32.efi|* + diff --git a/FSDrivers/ntfs.inf b/FSDrivers/ntfs.inf new file mode 100644 index 000000000000..804f655cd749 --- /dev/null +++ b/FSDrivers/ntfs.inf @@ -0,0 +1,27 @@ +# ReadOnly NTFS filesystem driver +# From https://efi.akeo.ie/ v1.5 +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ntfs + FILE_GUID = 2282efd0-678b-4753-8d06-200d5940285d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/ntfs_x64.efi|* + +[Binaries.IA32] + PE32|IA32/ntfs_ia32.efi|* + + diff --git a/MdeModulePkg/Application/UiApp/DeviceNameFromProduct.c b/MdeModulePkg/Application/UiApp/DeviceNameFromProduct.c new file mode 100644 index 000000000000..302726df59e9 --- /dev/null +++ b/MdeModulePkg/Application/UiApp/DeviceNameFromProduct.c @@ -0,0 +1,646 @@ +#include "FrontPage.h" + +VOID +GetDeviceNameFromProduct ( + IN CHAR16 *Product, + OUT CHAR16 **DeviceName + ) +{ + // grouped by platform + //SNB/IVB + if (!StrCmp(Product, L"Butterfly")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Pavilion Chromebook 14"); + } else if (!StrCmp(Product, L"Link")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Chromebook Pixel 2013"); + } else if (!StrCmp(Product, L"Lumpy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook Series 5 550"); + } else if (!StrCmp(Product, L"Parrot")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook C7/C710"); + } else if (!StrCmp(Product, L"Stout")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkPad X131e Chromebook"); + } else if (!StrCmp(Product, L"Stumpy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebox Series 3"); + } + //HSW + else if (!StrCmp(Product, L"Falco")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14"); + } else if (!StrCmp(Product, L"Leon")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Toshiba Chromebook"); + } else if (!StrCmp(Product, L"Mccloud")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebox CXI"); + } else if (!StrCmp(Product, L"Monroe")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"LG Chromebase"); + } else if (!StrCmp(Product, L"Panther")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebox CN60"); + } else if (!StrCmp(Product, L"Peppy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook C720"); + } else if (!StrCmp(Product, L"Tricky")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebox 3010"); + } else if (!StrCmp(Product, L"Wolf")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 2013"); + } else if (!StrCmp(Product, L"Zako")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebox CB1"); + } + //BDW + else if (!StrCmp(Product, L"Auron")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 11 [C740/C910]"); + } else if (!StrCmp(Product, L"Auron_Paine")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 11 [C740]"); + } else if (!StrCmp(Product, L"Auron_Yuna")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 [C910]"); + } else if (!StrCmp(Product, L"Buddy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebase 24"); + } else if (!StrCmp(Product, L"Gandof")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Toshiba Chromebook2 2015"); + } else if (!StrCmp(Product, L"Guado")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebox 2 / CN62"); + } else if (!StrCmp(Product, L"Lulu")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 13 7310"); + } else if (!StrCmp(Product, L"Rikku")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebox CXI2"); + } else if (!StrCmp(Product, L"Samus")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Chromebook Pixel 2015"); + } else if (!StrCmp(Product, L"Tidus")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkCentre Chromebox"); + } + //BYT + else if (!StrCmp(Product, L"Banjo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 [CB3-571]"); + } else if (!StrCmp(Product, L"Candy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3120"); + } else if (!StrCmp(Product, L"Clapper")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo N20 Chromebook"); + } else if (!StrCmp(Product, L"Enguarde")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo N21 Chromebook"); + } else if (!StrCmp(Product, L"Glimmer")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkPad 11e"); + } else if (!StrCmp(Product, L"Gnawty")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 11 [CB3-111/131]"); + } else if (!StrCmp(Product, L"Heli")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Haier Chromebook G2"); + } else if (!StrCmp(Product, L"Kip")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11 G3/G4"); + } else if (!StrCmp(Product, L"Ninja")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AOpen Chromebox Commercial"); + } else if (!StrCmp(Product, L"Orco")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Ideapad 100s"); + } else if (!StrCmp(Product, L"Quawks")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C300"); + } else if (!StrCmp(Product, L"Squawks")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C200"); + } else if (!StrCmp(Product, L"Sumo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AOpen Chromebase Commercial"); + } else if (!StrCmp(Product, L"Swanky")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Toshiba Chromebook2 2014"); + } else if (!StrCmp(Product, L"Winky")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook 2"); + } + //BSW + else if (!StrCmp(Product, L"Banon")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 [CB5-532]"); + } else if (!StrCmp(Product, L"Celes")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook 3"); + } else if (!StrCmp(Product, L"Cyan")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook R11 [C738T]"); + } else if (!StrCmp(Product, L"Edgar")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 14"); + } else if (!StrCmp(Product, L"Kefka")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3180/3189"); + } else if (!StrCmp(Product, L"Reks")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo N22 Chromebook"); + } else if (!StrCmp(Product, L"Relm")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 11 N7"); + } else if (!StrCmp(Product, L"Setzer")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11 G5"); + } else if (!StrCmp(Product, L"Terra")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C202SA/C300SA"); + } else if (!StrCmp(Product, L"Ultima")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkPad 11e/Yoga Chromebook (G3)"); + } else if (!StrCmp(Product, L"Wizpig")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"White Box Braswell Chromebook"); + } + //SKL + else if (!StrCmp(Product, L"Asuka")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 13 3380"); + } else if (!StrCmp(Product, L"Caroline")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook Pro"); + } else if (!StrCmp(Product, L"Cave")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C302"); + } else if (!StrCmp(Product, L"Chell")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 13 G1"); + } else if (!StrCmp(Product, L"Lars")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 14 for Work"); + } else if (!StrCmp(Product, L"Sentry")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkPad 13 Chromebook"); + } + //APL + else if (!StrCmp(Product, L"Astronaut")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 11 (C732)"); + } else if (!StrCmp(Product, L"Babymako")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C403"); + } else if (!StrCmp(Product, L"Babymega")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C223NA"); + } else if (!StrCmp(Product, L"Babytiger")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C523NA"); + } else if (!StrCmp(Product, L"Blacktip")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL7/NL7T"); + } else if (!StrCmp(Product, L"Blue")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 [CB315]"); + } else if (!StrCmp(Product, L"Bruce")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 15 [CP315]"); + } else if (!StrCmp(Product, L"Electro")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 11 [R751T]"); + } else if (!StrCmp(Product, L"Epaulette")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 514"); + } else if (!StrCmp(Product, L"Lava")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 11 [CP311]"); + } else if (!StrCmp(Product, L"Nasher")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 5190"); + } else if (!StrCmp(Product, L"Nasher360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 5190 2-in-1"); + } else if (!StrCmp(Product, L"Pyro")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Thinkpad 11e/Yoga 11e [G4]"); + } else if (!StrCmp(Product, L"Rabbid")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C423"); + } else if (!StrCmp(Product, L"Reef")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C213SA"); + } else if (!StrCmp(Product, L"Robo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 100e Chromebook"); + } else if (!StrCmp(Product, L"Robo360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 500e Chromebook"); + } else if (!StrCmp(Product, L"Sand")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 [CB515-1HT]"); + } else if (!StrCmp(Product, L"Santa")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 11 [CB311-8H]"); + } else if (!StrCmp(Product, L"Snappy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 11 G1/11 G6/14 G5"); + } else if (!StrCmp(Product, L"Whitetip")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook J41/J41T"); + } + //KBL + else if (!StrCmp(Product, L"Akali")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 13"); + } else if (!StrCmp(Product, L"Akali 360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 13"); + } else if (!StrCmp(Product, L"Atlas")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Pixelbook Go 2019"); + } else if (!StrCmp(Product, L"Bard")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 715"); + } else if (!StrCmp(Product, L"Ekko")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 714"); + } else if (!StrCmp(Product, L"Endeavour")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Meet Series One"); + } else if (!StrCmp(Product, L"Eve")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Pixelbook 2017"); + } else if (!StrCmp(Product, L"Excelsior")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Google Meet Kit (KBL)"); + } else if (!StrCmp(Product, L"Jax")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AOpen Chromebox Commercial 2"); + } else if (!StrCmp(Product, L"Karma")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebase 24I2"); + } else if (!StrCmp(Product, L"Kench")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebox G2"); + } else if (!StrCmp(Product, L"Leona")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C425"); + }else if (!StrCmp(Product, L"Nautilus")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook Plus V2"); + } else if (!StrCmp(Product, L"Nocturne")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Pixel Slate"); + } else if (!StrCmp(Product, L"Pantheon")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Yoga Chromebook C630"); + } else if (!StrCmp(Product, L"Rammus")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C425/C433/C434"); + } else if (!StrCmp(Product, L"Shyvana")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C433/C434"); + } else if (!StrCmp(Product, L"Sion")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebox CXI3"); + } else if (!StrCmp(Product, L"Sona")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14"); + } else if (!StrCmp(Product, L"Soraka")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x2"); + } else if (!StrCmp(Product, L"Syndra")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 15 G1"); + } else if (!StrCmp(Product, L"Teemo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebox 3 / CN65"); + } else if (!StrCmp(Product, L"Vayne")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Inspiron Chromebook 14"); + } else if (!StrCmp(Product, L"Wukong")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebox CBx1"); + } + //GLK + else if (!StrCmp(Product, L"Ampton")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C214/C234"); + } else if (!StrCmp(Product, L"Apel")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C204"); + } else if (!StrCmp(Product, L"Bloog")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 12b"); + } else if (!StrCmp(Product, L"Blooglet")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14a"); + } else if (!StrCmp(Product, L"Blooguard")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14a/14b"); + } else if (!StrCmp(Product, L"Blorb")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 315"); + } else if (!StrCmp(Product, L"Bluebird")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook 4"); + } else if (!StrCmp(Product, L"Bobba")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 311"); + } else if (!StrCmp(Product, L"Bobba360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 311/511"); + } else if (!StrCmp(Product, L"Casta")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook 4+"); + } else if (!StrCmp(Product, L"Dood")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"NEC Chromebook Y2"); + } else if (!StrCmp(Product, L"Dorp")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14 G6"); + } else if (!StrCmp(Product, L"Droid")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 314"); + } else if (!StrCmp(Product, L"Fleex")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 3100"); + } else if (!StrCmp(Product, L"Garg")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL71/CT/LTE"); + } else if (!StrCmp(Product, L"Garg360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL71T/TW/TWB"); + } else if (!StrCmp(Product, L"Garfour")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL81/NL81T"); + } else if (!StrCmp(Product, L"Glk")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 311"); + } else if (!StrCmp(Product, L"Glk360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 311"); + } else if (!StrCmp(Product, L"Grabbiter")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 3100 2-in-1"); + } else if (!StrCmp(Product, L"Foob")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook VX11/VX11T"); + } else if (!StrCmp(Product, L"Foob360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Poin2 Chromebook 11P"); + } else if (!StrCmp(Product, L"Laser")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Chromebook C340"); + } else if (!StrCmp(Product, L"Laser14")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Chromebook S340"); + } else if (!StrCmp(Product, L"Lick")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Ideapad 3 Chromebook"); + } else if (!StrCmp(Product, L"Meep")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 11 G2 EE"); + } else if (!StrCmp(Product, L"Mimrock")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11 G7 EE"); + } else if (!StrCmp(Product, L"Nospike")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook C424"); + } else if (!StrCmp(Product, L"Orbatrix")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 3400"); + } else if (!StrCmp(Product, L"Phaser")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 100e Chromebook 2nd Gen"); + } else if (!StrCmp(Product, L"Phaser360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 300e Chromebook 2nd Gen"); + } else if (!StrCmp(Product, L"Phaser360s")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 500e Chromebook 2nd Gen"); + } else if (!StrCmp(Product, L"Sparky")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 512"); + } else if (!StrCmp(Product, L"Sparky360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 512"); + } else if (!StrCmp(Product, L"Vorticon")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11 G8 EE"); + } else if (!StrCmp(Product, L"Vortininja")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 11 G3 EE"); + } + //WHL + else if (!StrCmp(Product, L"Arcada")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Latitude 5300 2-in-1 Chromebook Enterprise"); + } else if (!StrCmp(Product, L"Sarien")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Latitude 5400 Chromebook Enterprise"); + } + //CML + else if (!StrCmp(Product, L"Akemi")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Ideapad Flex 5 Chromebook"); + } else if (!StrCmp(Product, L"Ambassador")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Meet Compute System GQE15C"); + } else if (!StrCmp(Product, L"Dragonair")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14c"); + } else if (!StrCmp(Product, L"Drallion")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Latitude 7410 Chromebook Enterprise"); + } else if (!StrCmp(Product, L"Dratini")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Pro c640 Chromebook"); + } else if (!StrCmp(Product, L"Duffy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebox 4"); + } else if (!StrCmp(Product, L"Faffy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Fanless Chromebox"); + } else if (!StrCmp(Product, L"Helios")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C436FA"); + } else if (!StrCmp(Product, L"Jinlon")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Elite c1030 Chromebook / Chromebook x360 13c"); + } else if (!StrCmp(Product, L"Kaisa")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebox CXI4"); + } else if (!StrCmp(Product, L"Kindred")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 712"); + } else if (!StrCmp(Product, L"Kled")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 713 [CP713-2W]"); + } else if (!StrCmp(Product, L"Kohaku")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Galaxy Chromebook"); + } else if (!StrCmp(Product, L"Nightfury")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Galaxy Chromebook 2"); + } else if (!StrCmp(Product, L"Noibat")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebox G3"); + } else if (!StrCmp(Product, L"Wyvern")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebox CBx2"); + } + //Tigerlake + else if (!StrCmp(Product, L"Chronicler")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"FMV Chromebook 14F "); + } else if (!StrCmp(Product, L"Collis")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip CX3"); + } else if (!StrCmp(Product, L"Copano")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip CX5 [CX5400]"); + } else if (!StrCmp(Product, L"Delbin")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip CX55/CX5/C536"); + } else if (!StrCmp(Product, L"Drobit")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX9 [CX9400]"); + } else if (!StrCmp(Product, L"Eldrid")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14c"); + } else if (!StrCmp(Product, L"Elemi")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Pro c640 G2 Chromebook"); + } else if (!StrCmp(Product, L"Lillipup")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"IdeaPad Flex 5i Chromebook"); + } else if (!StrCmp(Product, L"Lindar")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 5i-14 Chromebook"); + } else if (!StrCmp(Product, L"Voema")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 514 [CB514-2H]"); + } else if (!StrCmp(Product, L"Volet")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 515 [CB515-1W/1WT]"); + } else if (!StrCmp(Product, L"Volta")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 514 [CB514-1W/1WT]"); + } else if (!StrCmp(Product, L"Voxel")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 713 [CP713-3W]"); + } + //Jasperlake + else if (!StrCmp(Product, L"Beadrix")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Beadrix JSL Chromebook"); + } else if (!StrCmp(Product, L"Beetley")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Flex 3i Chromebook"); + } else if (!StrCmp(Product, L"Blipper")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 3i-15 Chromebook"); + } else if (!StrCmp(Product, L"Bookem")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 100e Chromebook Gen 3"); + } else if (!StrCmp(Product, L"Boten")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 500e Chromebook Gen 3"); + } else if (!StrCmp(Product, L"Boxy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Chromebox Micro"); + } else if (!StrCmp(Product, L"Botenflex")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Flex 3i-11 Chromebook"); + } else if (!StrCmp(Product, L"Bugzzy")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Galaxy Chromebook 2 360"); + } else if (!StrCmp(Product, L"Cret")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 3110"); + } else if (!StrCmp(Product, L"Cret360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 3110 2-in-1"); + } else if (!StrCmp(Product, L"Dexi")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AOPEN Chromebox Mini 2"); + } else if (!StrCmp(Product, L"Drawcia")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 11 G4 EE"); + } else if (!StrCmp(Product, L"Drawlat")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11 G9 EE"); + } else if (!StrCmp(Product, L"Drawman")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14 G7"); + } else if (!StrCmp(Product, L"Drawper")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Fortis 14 G10 Chromebook"); + } else if (!StrCmp(Product, L"Galith")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX1500CKA"); + } else if (!StrCmp(Product, L"Galith360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX1500FKA"); + } else if (!StrCmp(Product, L"Gallop")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX1700CKA"); + } else if (!StrCmp(Product, L"Galnat")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX1 CX1102"); + } else if (!StrCmp(Product, L"Galnat360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip CX1 CX1102"); + } else if (!StrCmp(Product, L"Galtic")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX1"); + } else if (!StrCmp(Product, L"Galtic360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX1400FKA"); + } else if (!StrCmp(Product, L"Kracko")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL72"); + } else if (!StrCmp(Product, L"Kracko360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL72T"); + } else if (!StrCmp(Product, L"Landia")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14a-ca1"); + } else if (!StrCmp(Product, L"Landrid")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 15a-na0"); + } else if (!StrCmp(Product, L"Lantis")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14a"); + } else if (!StrCmp(Product, L"Madoo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14b"); + } else if (!StrCmp(Product, L"Magister")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 314"); + } else if (!StrCmp(Product, L"Maglet")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 512"); + } else if (!StrCmp(Product, L"Maglia")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 512"); + } else if (!StrCmp(Product, L"Maglith")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 511"); + } else if (!StrCmp(Product, L"Magma")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 315"); + } else if (!StrCmp(Product, L"Magneto")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 314"); + } else if (!StrCmp(Product, L"Magolor")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 511"); + } else if (!StrCmp(Product, L"Magpie")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 317"); + } else if (!StrCmp(Product, L"Metaknight")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"NEC Chromebook Y3"); + } else if (!StrCmp(Product, L"Palutena")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 314"); + } else if (!StrCmp(Product, L"Pasara")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Gateway Chromebook 15"); + } else if (!StrCmp(Product, L"Peezer")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 311"); + } else if (!StrCmp(Product, L"Pirette")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook PX11E"); + } else if (!StrCmp(Product, L"Pirika")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Gateway Chromebook 14"); + } else if (!StrCmp(Product, L"Sasuke")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Galaxy Chromebook Go"); + } else if (!StrCmp(Product, L"Sasukette")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Galaxy Chromebook Go 11"); + } else if (!StrCmp(Product, L"Storo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CR1100CKA"); + } else if (!StrCmp(Product, L"Storo360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip CR1100FKA"); + } else if (!StrCmp(Product, L"Taranza")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"ASUS Fanless Chromebox CF40"); + } + //Alderlake/Raptorlake-U/P + else if (!StrCmp(Product, L"Anahera")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Elite c640 14 inch G3 Chromebook"); + } else if (!StrCmp(Product, L"Aurash")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AOpen Chromebox Commercial 3"); + } else if (!StrCmp(Product, L"Banshee")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Framework Laptop Chromebook Edition"); + } else if (!StrCmp(Product, L"Constitution")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Meet Series Two"); + } else if (!StrCmp(Product, L"Crota")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Latitude 5430 Chromebook"); + } else if (!StrCmp(Product, L"Crota360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Latitude 5430 2-in-1 Chromebook"); + } else if (!StrCmp(Product, L"Dochi")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Plus Spin 514 [CP514-4HN]"); + } else if (!StrCmp(Product, L"Felwinter")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip CX5 [CX5601]"); + } else if (!StrCmp(Product, L"Gimble")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14c-cd0"); + } else if (!StrCmp(Product, L"Gladios")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebox Enterprise G4"); + } else if (!StrCmp(Product, L"Intrepid")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Meet Compute System GQE20C"); + } else if (!StrCmp(Product, L"Kano")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 714 [CP714-1WN]"); + } else if (!StrCmp(Product, L"Kinox")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkCentre M60q Chromebox"); + } else if (!StrCmp(Product, L"Kuldax")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"ASUS Chromebox 5 [CN67]"); + } else if (!StrCmp(Product, L"Lisbon")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebox CBx3"); + } else if (!StrCmp(Product, L"Marasov")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX34"); + } else if (!StrCmp(Product, L"Mithrax")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CX34 Flip"); + } else if (!StrCmp(Product, L"Moli")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebox CXI5"); + } else if (!StrCmp(Product, L"Omnigul")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Plus 515 [CB515-2H]"); + } else if (!StrCmp(Product, L"Omniknight")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Plus Enterprise 515"); + } else if (!StrCmp(Product, L"Osiris")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 516 GE [CBG516-1H]"); + } else if (!StrCmp(Product, L"Primus")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkPad C14 Gen 1 Chromebook"); + } else if (!StrCmp(Product, L"Redrix")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Elite Dragonfly Chromebook"); + } else if (!StrCmp(Product, L"Taeko")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Flex 5i Chromebook"); + } else if (!StrCmp(Product, L"Taniks")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo IdeaPad Gaming Chromebook 16"); + } else if (!StrCmp(Product, L"Tarlo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 5i Chromebook 16\""); + } else if (!StrCmp(Product, L"Vell")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Dragonfly Pro Chromebook"); + } else if (!StrCmp(Product, L"Volmar")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Vero 514"); + } else if (!StrCmp(Product, L"Zavala")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Vero 712"); + } + //Alderlake-N + else if (!StrCmp(Product, L"Anraggar")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"ASUS Chromebook CR12"); + } else if (!StrCmp(Product, L"Anraggar360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"ASUS Chromebook CR12 Flip"); + } else if (!StrCmp(Product, L"Craask")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 512"); + } else if (!StrCmp(Product, L"Craaskana")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 311"); + } else if (!StrCmp(Product, L"Craaskbowl")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 511"); + } else if (!StrCmp(Product, L"Craaskino")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 315"); + } else if (!StrCmp(Product, L"Craaskov")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 312"); + } else if (!StrCmp(Product, L"Craaskvin")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 511"); + } else if (!StrCmp(Product, L"Craasneto")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 314"); + } else if (!StrCmp(Product, L"Joxer")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"TBD ADL-N Chromebook"); + } else if (!StrCmp(Product, L"Joxero")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"TBD ADL-N Chromebook"); + } else if (!StrCmp(Product, L"Nereid")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"TBD ADL-N Chromebook"); + } else if (!StrCmp(Product, L"Nirwin")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"TBD ADL-N Chromebook"); + } else if (!StrCmp(Product, L"Nivviks")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"TBD ADL-N Chromebook"); + } else if (!StrCmp(Product, L"Pujjo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo IdeaPad Flex 3i Chromebook"); + } else if (!StrCmp(Product, L"Pujjoflex")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo IdeaPad Flex 3i Chromebook"); + } else if (!StrCmp(Product, L"Pujjoteen")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 14e Chromebook Gen 3"); + } else if (!StrCmp(Product, L"Pujjoteen15w")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo Ideapad Slim 3i Chromebook"); + } else if (!StrCmp(Product, L"Quandiso")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL73"); + } else if (!StrCmp(Product, L"Quandiso360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"CTL Chromebook NL73T"); + } else if (!StrCmp(Product, L"Uldren")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 3120"); + } else if (!StrCmp(Product, L"Uldren360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 3120 2-in-1"); + } else if (!StrCmp(Product, L"Xivu")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook CR11 [CR1102C]"); + } else if (!StrCmp(Product, L"Yahiko")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14a-nf0xxx"); + } else if (!StrCmp(Product, L"Yavijo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Fortis 14\" G11 Chromebook"); + } else if (!StrCmp(Product, L"Yaviks")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 15.6"); + } else if (!StrCmp(Product, L"Yavikso")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"TBD ADL-N Chromebook"); + } else if (!StrCmp(Product, L"Yavilla")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Fortis 11\" G10 Chromebook"); + } else if (!StrCmp(Product, L"Yavilly")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Fortis x360 11\" G5 Chromebook"); + } + //Meteorlake + else if (!StrCmp(Product, L"Screebo")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"ASUS ExpertBook CX54 Chromebook Plus [CX5403]"); + } + //AMD StoneyRidge + else if (!StrCmp(Product, L"Aleena")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 315"); + } else if (!StrCmp(Product, L"Barla")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11A G6 EE"); + } else if (!StrCmp(Product, L"Careena")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14"); + } else if (!StrCmp(Product, L"Grunt")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AMD StonyRidge Chromebook"); + } else if (!StrCmp(Product, L"Kasumi")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 311"); + } else if (!StrCmp(Product, L"Liara")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 14e Chromebook"); + } else if (!StrCmp(Product, L"Treeya")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 100e Chromebook 2nd Gen"); + } else if (!StrCmp(Product, L"Treeya360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 300e Chromebook 2nd Gen"); + } + // AMD Picasso + else if (!StrCmp(Product, L"Berknip")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Pro c645 Chromebook Enterprise"); + } else if (!StrCmp(Product, L"Dirinboz")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14a"); + } else if (!StrCmp(Product, L"Ezkinil")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 514"); + } else if (!StrCmp(Product, L"Gumboz")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook x360 14a"); + } else if (!StrCmp(Product, L"Morphius")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo ThinkPad C13 Yoga Chromebook"); + } else if (!StrCmp(Product, L"Vilboz")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 100e Chromebook Gen 3"); + } else if (!StrCmp(Product, L"Vilboz14")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 14e Chromebook Gen 2"); + } else if (!StrCmp(Product, L"Vilboz360")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 300e Chromebook Gen 3"); + } else if (!StrCmp(Product, L"Woomax")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip CM5"); + } + // AMD Cezanne + else if (!StrCmp(Product, L"Dewatt")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 514"); + } else if (!StrCmp(Product, L"Nipperkin")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Elite c645 G2 Chroembook"); + } + // AMD Mendocino + else if (!StrCmp(Product, L"Crystaldrift")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"TBD Skyrim Chromebook"); + } else if (!StrCmp(Product, L"Frostflow")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"ASUS Chromebook CM34 Flip"); + } else if (!StrCmp(Product, L"Markarth")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Plus 514"); + } else if (!StrCmp(Product, L"Whiterun")) { + StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Latitude 3445 Chromebook"); + } +} diff --git a/MdeModulePkg/Application/UiApp/FrontPage.c b/MdeModulePkg/Application/UiApp/FrontPage.c index 0e784fb327f5..03b97ca7b0ec 100644 --- a/MdeModulePkg/Application/UiApp/FrontPage.c +++ b/MdeModulePkg/Application/UiApp/FrontPage.c @@ -442,7 +442,7 @@ ConvertMemorySizeToString ( StringBuffer = AllocateZeroPool (0x24); ASSERT (StringBuffer != NULL); UnicodeValueToStringS (StringBuffer, 0x24, LEFT_JUSTIFY, MemorySize, 10); - StrCatS (StringBuffer, 0x24 / sizeof (CHAR16), L" MB RAM"); + StrCatS (StringBuffer, 0x24 / sizeof (CHAR16), L" MB"); *String = (CHAR16 *)StringBuffer; @@ -508,7 +508,6 @@ UpdateFrontPageBannerStrings ( { UINT8 StrIndex; CHAR16 *NewString; - CHAR16 *FirmwareVersionString; EFI_STATUS Status; EFI_SMBIOS_HANDLE SmbiosHandle; EFI_SMBIOS_PROTOCOL *Smbios; @@ -523,62 +522,14 @@ UpdateFrontPageBannerStrings ( InstalledMemory = 0; FoundCpu = 0; - // - // Update default banner string. - // - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_LEFT), NULL); - UiCustomizeFrontPageBanner (4, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_LEFT), NewString, NULL); - FreePool (NewString); - - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_RIGHT), NULL); - UiCustomizeFrontPageBanner (4, FALSE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_RIGHT), NewString, NULL); - FreePool (NewString); - - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_LEFT), NULL); - UiCustomizeFrontPageBanner (5, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_LEFT), NewString, NULL); - FreePool (NewString); - - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_RIGHT), NULL); - UiCustomizeFrontPageBanner (5, FALSE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_RIGHT), NewString, NULL); - FreePool (NewString); - // // Update Front Page banner strings base on SmBios Table. // Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios); if (EFI_ERROR (Status)) { // - // Smbios protocol not found, get the default value. + // Smbios protocol not found // - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), NULL); - UiCustomizeFrontPageBanner (1, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), NewString, NULL); - FreePool (NewString); - - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL), NULL); - UiCustomizeFrontPageBanner (2, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL), NewString, NULL); - FreePool (NewString); - - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED), NULL); - UiCustomizeFrontPageBanner (2, FALSE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED), NewString, NULL); - FreePool (NewString); - - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NULL); - UiCustomizeFrontPageBanner (3, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL); - FreePool (NewString); - - NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), NULL); - UiCustomizeFrontPageBanner (3, FALSE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), NewString, NULL); - FreePool (NewString); - return; } @@ -586,33 +537,74 @@ UpdateFrontPageBannerStrings ( Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); while (!EFI_ERROR (Status)) { if (Record->Type == SMBIOS_TYPE_BIOS_INFORMATION) { + CHAR16 *FwVersion; + CHAR16 *FwDate; + CHAR16 *TmpBuffer; + UINT8 VersionIdx; + UINT8 DateIdx; + Type0Record = (SMBIOS_TABLE_TYPE0 *)Record; - StrIndex = Type0Record->BiosVersion; - GetOptionalStringByIndex ((CHAR8 *)((UINT8 *)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString); + VersionIdx = Type0Record->BiosVersion; + DateIdx = Type0Record->BiosReleaseDate; - FirmwareVersionString = (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString); - if (*FirmwareVersionString != 0x0000 ) { - FreePool (NewString); - NewString = (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString); - UiCustomizeFrontPageBanner (3, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL); - } else { - UiCustomizeFrontPageBanner (3, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL); - FreePool (NewString); - } + TmpBuffer = AllocateZeroPool (0x60); + GetOptionalStringByIndex ((CHAR8 *)((UINT8 *)Type0Record + Type0Record->Hdr.Length), VersionIdx, &FwVersion); + GetOptionalStringByIndex ((CHAR8 *)((UINT8 *)Type0Record + Type0Record->Hdr.Length), DateIdx, &FwDate); + + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), L" FW: "); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), FwVersion); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), L" "); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), FwDate); + + HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), TmpBuffer, NULL); + + FreePool (FwVersion); + FreePool (FwDate); + FreePool (TmpBuffer); } if (Record->Type == SMBIOS_TYPE_SYSTEM_INFORMATION) { + CHAR16 *ProductName; + CHAR16 *Manufacturer; + CHAR16 *DeviceName; + CHAR16 *TmpBuffer; + UINT8 ProductIdx; + UINT8 ManIdx; + Type1Record = (SMBIOS_TABLE_TYPE1 *)Record; - StrIndex = Type1Record->ProductName; - GetOptionalStringByIndex ((CHAR8 *)((UINT8 *)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString); - UiCustomizeFrontPageBanner (1, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), NewString, NULL); - FreePool (NewString); + ProductIdx = Type1Record->ProductName; + ManIdx = Type1Record->Manufacturer; + + TmpBuffer = AllocateZeroPool (0x60); + DeviceName = AllocateZeroPool (0x60); + + GetOptionalStringByIndex ((CHAR8 *)((UINT8 *)Type1Record + Type1Record->Hdr.Length), ProductIdx, &ProductName); + GetOptionalStringByIndex ((CHAR8 *)((UINT8 *)Type1Record + Type1Record->Hdr.Length), ManIdx, &Manufacturer); + + //see if we have a device name to show + GetDeviceNameFromProduct(ProductName, &DeviceName); + + if (DeviceName[0] != 0) { + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), DeviceName); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), L" ("); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), ProductName); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), L")"); + } else { + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), Manufacturer); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), L" "); + StrCatS (TmpBuffer, 0x60 / sizeof (CHAR16), ProductName); + } + + HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), TmpBuffer, NULL); + + FreePool (ProductName); + FreePool (Manufacturer); + FreePool (DeviceName); + FreePool (TmpBuffer); } if ((Record->Type == SMBIOS_TYPE_PROCESSOR_INFORMATION) && !FoundCpu) { + CHAR16 *TmpBuffer; Type4Record = (SMBIOS_TABLE_TYPE4 *)Record; // // The information in the record should be only valid when the CPU Socket is populated. @@ -620,14 +612,21 @@ UpdateFrontPageBannerStrings ( if ((Type4Record->Status & SMBIOS_TYPE4_CPU_SOCKET_POPULATED) == SMBIOS_TYPE4_CPU_SOCKET_POPULATED) { StrIndex = Type4Record->ProcessorVersion; GetOptionalStringByIndex ((CHAR8 *)((UINT8 *)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString); - UiCustomizeFrontPageBanner (2, TRUE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL), NewString, NULL); - FreePool (NewString); - - ConvertProcessorToString (Type4Record->CurrentSpeed, 6, &NewString); - UiCustomizeFrontPageBanner (2, FALSE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED), NewString, NULL); + // Trim leading spaces + while (NewString[0] == 0x20) { + NewString = &NewString[1]; + } + // Drop 'CPU @ ' if present in string + CHAR16 *Truncate = StrStr(NewString, L"CPU"); + if (Truncate != NULL) { + *Truncate = L'\0'; + } + // Add 'CPU: ' prefix + TmpBuffer = AllocateZeroPool (0x60); + UnicodeSPrint (TmpBuffer, 0x60 * sizeof (CHAR16), L"%s%s", L"CPU: ", NewString); + HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL), TmpBuffer, NULL); FreePool (NewString); + FreePool (TmpBuffer); FoundCpu = TRUE; } @@ -657,9 +656,11 @@ UpdateFrontPageBannerStrings ( // Now update the total installed RAM size // ConvertMemorySizeToString ((UINT32)InstalledMemory, &NewString); - UiCustomizeFrontPageBanner (3, FALSE, &NewString); - HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), NewString, NULL); + CHAR16 *TmpBuffer = AllocateZeroPool (0x60); + UnicodeSPrint (TmpBuffer, 0x60 * sizeof (CHAR16), L"%s%s", L"RAM: ", NewString); + HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), TmpBuffer, NULL); FreePool (NewString); + FreePool (TmpBuffer); } /** diff --git a/MdeModulePkg/Application/UiApp/FrontPage.h b/MdeModulePkg/Application/UiApp/FrontPage.h index efabc9ed1a1f..e1faeeb153f2 100644 --- a/MdeModulePkg/Application/UiApp/FrontPage.h +++ b/MdeModulePkg/Application/UiApp/FrontPage.h @@ -208,3 +208,16 @@ ExtractDevicePathFromHiiHandle ( ); #endif // _FRONT_PAGE_H_ + +/** + Get Device Name string from SMBIOS product name + + @param Product SMBIOS product name string + @param DeviceName returned Device name string + +**/ +VOID +GetDeviceNameFromProduct ( + IN CHAR16 *Product, + OUT CHAR16 **DeviceName + ); diff --git a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.c b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.c index f2458ec5a0c8..cd5e3e0b98b3 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.c +++ b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.c @@ -30,9 +30,9 @@ UiCustomizeFrontPage ( ) { // - // Create "Select Language" menu with Oneof opcode. + // Create "Continue" menu. // - UiCreateLanguageMenu (HiiHandle, StartOpCodeHandle); + UiCreateContinueMenu(HiiHandle, StartOpCodeHandle); // // Create empty line. @@ -49,11 +49,6 @@ UiCustomizeFrontPage ( // UiCreateEmptyLine (HiiHandle, StartOpCodeHandle); - // - // Create "Continue" menu. - // - UiCreateContinueMenu (HiiHandle, StartOpCodeHandle); - // // Create reset menu. // @@ -96,46 +91,3 @@ UiFrontPageCallbackHandler ( return EFI_UNSUPPORTED; } - -/** - Update the banner string in the front page. - - Current layout for the banner string like below: - PS: Totally only 5 lines of banner supported. - - Line 1: Left BannerStr RightBannerStr - Line 2: Left BannerStr RightBannerStr - Line 3: Left BannerStr RightBannerStr - Line 4: Left BannerStr RightBannerStr - Line 5: Left BannerStr RightBannerStr - - First menu in front page. - ... - - @param LineIndex The line index of the banner need to check. - @param LeftOrRight The left or right banner need to check. - @param BannerStr Banner string need to update. - Input the current string and user can update - it and return the new string. - -**/ -VOID -UiCustomizeFrontPageBanner ( - IN UINTN LineIndex, - IN BOOLEAN LeftOrRight, - IN OUT EFI_STRING *BannerStr - ) -{ - if ((LineIndex == 5) && LeftOrRight) { - // Update STR_CUSTOMIZE_BANNER_LINE5_LEFT - if (PcdGetBool (PcdTestKeyUsed)) { - if (BannerStr != NULL) { - FreePool (*BannerStr); - } - - *BannerStr = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_TEST_KEY_USED), NULL); - } - } - - return; -} diff --git a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.h b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.h index b53909e21716..81e548cb288d 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.h +++ b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUi.h @@ -9,35 +9,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #ifndef __FRONTPAGE_CUSTOMIZED_UI_H__ #define __FRONTPAGE_CUSTOMIZED_UI_H__ -/** - Update the banner string in the front page. - - Current layout for the banner string like below: - PS: Totally only 5 lines of banner supported. - - Line 1: Left BannerStr RightBannerStr - Line 2: Left BannerStr RightBannerStr - Line 3: Left BannerStr RightBannerStr - Line 4: Left BannerStr RightBannerStr - Line 5: Left BannerStr RightBannerStr - - First menu in front page. - ... - - @param LineIndex The line index of the banner need to check. - @param LeftOrRight The left or right banner need to check. - @param BannerStr Banner string need to update. - Input the current string and user can update - it and return the new string. - -**/ -VOID -UiCustomizeFrontPageBanner ( - IN UINTN LineIndex, - IN BOOLEAN LeftOrRight, - IN OUT EFI_STRING *BannerStr - ); - /** Customize menus in the page. diff --git a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c index 24f9f1e3fb02..dff2d2128a44 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c +++ b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c @@ -30,13 +30,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent // This is the VFR compiler generated header file which defines the // string identifiers. // -#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001 #define UI_HII_DRIVER_LIST_SIZE 0x8 #define FRONT_PAGE_KEY_CONTINUE 0x1000 #define FRONT_PAGE_KEY_RESET 0x1001 -#define FRONT_PAGE_KEY_LANGUAGE 0x1002 #define FRONT_PAGE_KEY_DRIVER 0x2000 typedef struct { @@ -47,112 +45,9 @@ typedef struct { BOOLEAN EmptyLineAfter; } UI_HII_DRIVER_INSTANCE; -CHAR8 *gLanguageString; -EFI_STRING_ID *gLanguageToken; UI_HII_DRIVER_INSTANCE *gHiiDriverList; extern EFI_HII_HANDLE gStringPackHandle; -UINT8 gCurrentLanguageIndex; -/** - Get next language from language code list (with separator ';'). - - If LangCode is NULL, then ASSERT. - If Lang is NULL, then ASSERT. - - @param LangCode On input: point to first language in the list. On - output: point to next language in the list, or - NULL if no more language in the list. - @param Lang The first language in the list. - -**/ -VOID -GetNextLanguage ( - IN OUT CHAR8 **LangCode, - OUT CHAR8 *Lang - ) -{ - UINTN Index; - CHAR8 *StringPtr; - - ASSERT (LangCode != NULL); - ASSERT (*LangCode != NULL); - ASSERT (Lang != NULL); - - Index = 0; - StringPtr = *LangCode; - while (StringPtr[Index] != 0 && StringPtr[Index] != ';') { - Index++; - } - - CopyMem (Lang, StringPtr, Index); - Lang[Index] = 0; - - if (StringPtr[Index] == ';') { - Index++; - } - - *LangCode = StringPtr + Index; -} - -/** - This function processes the language changes in configuration. - - @param Value A pointer to the data being sent to the original exporting driver. - - - @retval TRUE The callback successfully handled the action. - @retval FALSE The callback not supported in this handler. - -**/ -EFI_STATUS -LanguageChangeHandler ( - IN EFI_IFR_TYPE_VALUE *Value - ) -{ - CHAR8 *LangCode; - CHAR8 *Lang; - UINTN Index; - EFI_STATUS Status; - - // - // Allocate working buffer for RFC 4646 language in supported LanguageString. - // - Lang = AllocatePool (AsciiStrSize (gLanguageString)); - ASSERT (Lang != NULL); - - Index = 0; - LangCode = gLanguageString; - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - - if (Index == Value->u8) { - gCurrentLanguageIndex = Value->u8; - break; - } - - Index++; - } - - if (Index == Value->u8) { - Status = gRT->SetVariable ( - L"PlatformLang", - &gEfiGlobalVariableGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - AsciiStrSize (Lang), - Lang - ); - if (EFI_ERROR (Status)) { - FreePool (Lang); - return EFI_DEVICE_ERROR; - } - } else { - ASSERT (FALSE); - } - - FreePool (Lang); - - return EFI_SUCCESS; -} /** This function processes the results of changes in configuration. @@ -183,20 +78,13 @@ UiSupportLibCallbackHandler ( ) { if ((QuestionId != FRONT_PAGE_KEY_CONTINUE) && - (QuestionId != FRONT_PAGE_KEY_RESET) && - (QuestionId != FRONT_PAGE_KEY_LANGUAGE)) + (QuestionId != FRONT_PAGE_KEY_RESET)) { return FALSE; } if (Action == EFI_BROWSER_ACTION_RETRIEVE) { - if (QuestionId == FRONT_PAGE_KEY_LANGUAGE) { - Value->u8 = gCurrentLanguageIndex; - *Status = EFI_SUCCESS; - } else { - *Status = EFI_UNSUPPORTED; - } - + *Status = EFI_UNSUPPORTED; return TRUE; } @@ -223,10 +111,6 @@ UiSupportLibCallbackHandler ( *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; break; - case FRONT_PAGE_KEY_LANGUAGE: - *Status = LanguageChangeHandler (Value); - break; - case FRONT_PAGE_KEY_RESET: // // Reset @@ -242,160 +126,6 @@ UiSupportLibCallbackHandler ( return TRUE; } -/** - Create Select language menu in the front page with oneof opcode. - - @param[in] HiiHandle The hii handle for the Uiapp driver. - @param[in] StartOpCodeHandle The opcode handle to save the new opcode. - -**/ -VOID -UiCreateLanguageMenu ( - IN EFI_HII_HANDLE HiiHandle, - IN VOID *StartOpCodeHandle - ) -{ - CHAR8 *LangCode; - CHAR8 *Lang; - UINTN LangSize; - CHAR8 *CurrentLang; - UINTN OptionCount; - CHAR16 *StringBuffer; - VOID *OptionsOpCodeHandle; - UINTN StringSize; - EFI_STATUS Status; - EFI_HII_STRING_PROTOCOL *HiiString; - - Lang = NULL; - StringBuffer = NULL; - - // - // Init OpCode Handle and Allocate space for creation of UpdateData Buffer - // - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&CurrentLang, NULL); - - // - // Get Support language list from variable. - // - GetEfiGlobalVariable2 (L"PlatformLangCodes", (VOID **)&gLanguageString, NULL); - if (gLanguageString == NULL) { - gLanguageString = AllocateCopyPool ( - AsciiStrSize ((CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)), - (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) - ); - ASSERT (gLanguageString != NULL); - } - - if (gLanguageToken == NULL) { - // - // Count the language list number. - // - LangCode = gLanguageString; - Lang = AllocatePool (AsciiStrSize (gLanguageString)); - ASSERT (Lang != NULL); - - OptionCount = 0; - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - OptionCount++; - } - - // - // Allocate extra 1 as the end tag. - // - gLanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID)); - ASSERT (gLanguageToken != NULL); - - Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **)&HiiString); - ASSERT_EFI_ERROR (Status); - - LangCode = gLanguageString; - OptionCount = 0; - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - - StringSize = 0; - Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); - if (Status == EFI_BUFFER_TOO_SMALL) { - StringBuffer = AllocateZeroPool (StringSize); - ASSERT (StringBuffer != NULL); - Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); - ASSERT_EFI_ERROR (Status); - } - - if (EFI_ERROR (Status)) { - LangSize = AsciiStrSize (Lang); - StringBuffer = AllocatePool (LangSize * sizeof (CHAR16)); - ASSERT (StringBuffer != NULL); - AsciiStrToUnicodeStrS (Lang, StringBuffer, LangSize); - } - - ASSERT (StringBuffer != NULL); - gLanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL); - FreePool (StringBuffer); - - OptionCount++; - } - } - - ASSERT (gLanguageToken != NULL); - LangCode = gLanguageString; - OptionCount = 0; - if (Lang == NULL) { - Lang = AllocatePool (AsciiStrSize (gLanguageString)); - ASSERT (Lang != NULL); - } - - while (*LangCode != 0) { - GetNextLanguage (&LangCode, Lang); - - if ((CurrentLang != NULL) && (AsciiStrCmp (Lang, CurrentLang) == 0)) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - gLanguageToken[OptionCount], - EFI_IFR_OPTION_DEFAULT, - EFI_IFR_NUMERIC_SIZE_1, - (UINT8)OptionCount - ); - gCurrentLanguageIndex = (UINT8)OptionCount; - } else { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - gLanguageToken[OptionCount], - 0, - EFI_IFR_NUMERIC_SIZE_1, - (UINT8)OptionCount - ); - } - - OptionCount++; - } - - if (CurrentLang != NULL) { - FreePool (CurrentLang); - } - - FreePool (Lang); - - HiiCreateOneOfOpCode ( - StartOpCodeHandle, - FRONT_PAGE_KEY_LANGUAGE, - 0, - 0, - STRING_TOKEN (STR_LANGUAGE_SELECT), - STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), - EFI_IFR_FLAG_CALLBACK, - EFI_IFR_NUMERIC_SIZE_1, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); -} - /** Create continue menu in the front page. @@ -412,8 +142,8 @@ UiCreateContinueMenu ( HiiCreateActionOpCode ( StartOpCodeHandle, FRONT_PAGE_KEY_CONTINUE, - STRING_TOKEN (STR_CONTINUE_PROMPT), - STRING_TOKEN (STR_CONTINUE_PROMPT), + STRING_TOKEN (STR_BOOT_DEFAULT_PROMPT), + STRING_TOKEN (STR_BOOT_DEFAULT_HELP), EFI_IFR_FLAG_CALLBACK, 0 ); @@ -670,9 +400,8 @@ UiListThirdPartyDrivers ( gHiiDriverList[Index].DevicePathId ); - if (gHiiDriverList[Index].EmptyLineAfter) { - UiCreateEmptyLine (HiiHandle, StartOpCodeHandle); - } + // Always add an empty line after each entry + UiCreateEmptyLine (HiiHandle, StartOpCodeHandle); Index++; } diff --git a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.h b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.h index c4fddebc2749..aea77662d4f9 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.h +++ b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.h @@ -35,19 +35,6 @@ UiCreateEmptyLine ( IN VOID *StartOpCodeHandle ); -/** - Create Select language menu in the front page with oneof opcode. - - @param[in] HiiHandle The hii handle for the Uiapp driver. - @param[in] StartOpCodeHandle The opcode handle to save the new opcode. - -**/ -VOID -UiCreateLanguageMenu ( - IN EFI_HII_HANDLE HiiHandle, - IN VOID *StartOpCodeHandle - ); - /** Create Reset menu. diff --git a/MdeModulePkg/Application/UiApp/FrontPageStrings.uni b/MdeModulePkg/Application/UiApp/FrontPageStrings.uni index bd6e377cc106..09a46fb30677 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageStrings.uni +++ b/MdeModulePkg/Application/UiApp/FrontPageStrings.uni @@ -10,59 +10,17 @@ /=# #langdef en-US "English" -#langdef fr-FR "Français" #langdef en "Standard English" -#langdef fr "Standard Français" #string STR_FRONT_PAGE_TITLE #language en-US "Front Page" - #language fr-FR "Front Page" -#string STR_FRONT_PAGE_COMPUTER_MODEL #language en-US "" - #language fr-FR "" -#string STR_FRONT_PAGE_CPU_MODEL #language en-US "" - #language fr-FR "" -#string STR_FRONT_PAGE_CPU_SPEED #language en-US "" - #language fr-FR "" +#string STR_FRONT_PAGE_COMPUTER_MODEL #language en-US "" +#string STR_FRONT_PAGE_BIOS_VERSION #language en-US "" +#string STR_FRONT_PAGE_CPU_MODEL #language en-US "" #string STR_FRONT_PAGE_MEMORY_SIZE #language en-US "" - #language fr-FR "" -#string STR_FRONT_PAGE_BIOS_VERSION #language en-US "" - #language fr-FR "" -#string STR_FRONT_PAGE_BANNER_0_LEFT #language en-US "Wonder Computer Model 1000Z Manufactured by Intel®" - #language fr-FR "Demander le Modèle d'Ordinateur 1000Z A Fabriqué par Intel®" -#string STR_FRONT_PAGE_BANNER_0_RIGHT #language en-US "OK" - #language fr-FR "Bon" -#string STR_FRONT_PAGE_BANNER_1_LEFT #language en-US "2 Pentium® X Xeon processors running at 800Thz" - #language fr-FR "2 processeurs Pentium® X Xeon tournants à 800Thz" -#string STR_FRONT_PAGE_BANNER_1_RIGHT #language en-US "24 TB System RAM" - #language fr-FR "24 TB RAM de Système" -#string STR_FRONT_PAGE_BANNER_2_LEFT #language en-US "ACME® EFI BIOS Version 13.5 Release 1039.92" - #language fr-FR "ACME® EFI BIOS Version 13.5 Release 1039.92" -#string STR_FRONT_PAGE_BANNER_3_LEFT #language en-US "Serial Number: 1Z123456789MARMAR (Need SMBIOS entries)" - #language fr-FR "Numéro de série: 1Z123456789MARMAR (Les entrées de SMBIOS de besoin)" -#string STR_CONTINUE_PROMPT #language en-US "Continue" - #language fr-FR "Continuer" -#string STR_CONTINUE_HELP #language en-US "This selection will direct the system to continue to booting process" - #language fr-FR "Cette sélection dirigera le système pour continuer au processus d'amorçage" -#string STR_LANGUAGE_SELECT #language en-US "Select Language" - #language fr-FR "Choisir la Langue" -#string STR_LANGUAGE_SELECT_HELP #language en-US "This is the option one adjusts to change the language for the current system" - #language fr-FR "Ceci est l'option qu'on ajuste pour changer la langue pour le système actuel" +#string STR_BOOT_DEFAULT_PROMPT #language en-US "Default Boot" +#string STR_BOOT_DEFAULT_HELP #language en-US "Boot the Default Selection" #string STR_MISSING_STRING #language en-US "Missing String" - #language fr-FR "Missing String" #string STR_EMPTY_STRING #language en-US "" - #language fr-FR "" -#string STR_RESET_STRING #language en-US "Reset" - #language fr-FR "Réinitialiser" -#string STR_RESET_STRING_HELP #language en-US "Cold reset (reboots the computer)." - #language fr-FR "Réinitialisation à froid (redémarre l'ordinateur)." -#string STR_CUSTOMIZE_BANNER_LINE4_LEFT #language en-US "" - #language fr-FR "" -#string STR_CUSTOMIZE_BANNER_LINE4_RIGHT #language en-US "" - #language fr-FR "" -#string STR_CUSTOMIZE_BANNER_LINE5_LEFT #language en-US "" - #language fr-FR "" -#string STR_CUSTOMIZE_BANNER_LINE5_RIGHT #language en-US "" - #language fr-FR "" -#string STR_TEST_KEY_USED #language en-US "WARNING: Test key detected." - #language fr-FR "WARNING: Test key detected." +#string STR_RESET_STRING #language en-US "Reboot" +#string STR_RESET_STRING_HELP #language en-US "Reboot the device" #string STR_NULL_STRING #language en-US " " - #language fr-FR " " diff --git a/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr b/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr index ac40c4676e2e..d01543016f39 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr +++ b/MdeModulePkg/Application/UiApp/FrontPageVfr.Vfr @@ -17,7 +17,7 @@ formset guid = FORMSET_GUID, title = STRING_TOKEN(STR_FRONT_PAGE_TITLE), - help = STRING_TOKEN(STR_EMPTY_STRING ), + help = STRING_TOKEN(STR_EMPTY_STRING), classguid = FORMSET_GUID, form formid = FRONT_PAGE_FORM_ID, @@ -26,17 +26,7 @@ formset banner title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL), line 1, - align left; - - banner - title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL), - line 2, - align left; - - banner - title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED), - line 2, - align right; + align center; banner title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION), @@ -44,29 +34,16 @@ formset align left; banner - title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE), - line 3, - align right; - - banner - title = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE4_LEFT), + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL), line 4, align left; banner - title = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE4_RIGHT), - line 4, - align right; - - banner - title = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE5_LEFT), + title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE), line 5, align left; - banner - title = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE5_RIGHT), - line 5, - align right; + subtitle text = STRING_TOKEN(STR_NULL_STRING); label LABEL_FRONTPAGE_INFORMATION; // diff --git a/MdeModulePkg/Application/UiApp/UiApp.inf b/MdeModulePkg/Application/UiApp/UiApp.inf index 3b9e048851fe..2c95cf6c62df 100644 --- a/MdeModulePkg/Application/UiApp/UiApp.inf +++ b/MdeModulePkg/Application/UiApp/UiApp.inf @@ -33,6 +33,7 @@ FrontPageCustomizedUiSupport.c FrontPageCustomizedUi.h FrontPageCustomizedUiSupport.h + DeviceNameFromProduct.c [Packages] MdePkg/MdePkg.dec diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c index 5c4b215f7ac7..c26bbcdff67c 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c @@ -2743,6 +2743,9 @@ IsPciDeviceRejected ( return FALSE; } + // This code is buggy AF, so don't reject anything + return FALSE; + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { // // Only test base registers for P2C diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c index a392a4e31aa7..8bc90b1d24c7 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c @@ -522,15 +522,33 @@ EmmcTuningClkForHs200 ( return Status; } + if(BhtHostPciSupport(PciIo)) { + //set data transfer with 4bit + Status = SdMmcHcSetBusWidth (PciIo, Slot, 4); + //enable hardware tuning + HostCtrl2 = (UINT8)(~0x10); + Status = SdMmcHcAndMmio (PciIo, Slot, 0x110,sizeof (HostCtrl2), &HostCtrl2); + + Status = EmmcSendTuningBlk (PassThru, Slot, 4); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status)); + return Status; + } + } + // // Ask the device to send a sequence of tuning blocks till the tuning procedure is done. // Retry = 0; do { - Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status)); - return Status; + if(!BhtHostPciSupport(PciIo)) { + Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status)); + return Status; + } + } else { + gBS->Stall(5000); } Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2); @@ -543,6 +561,10 @@ EmmcTuningClkForHs200 ( } if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) { + if(BhtHostPciSupport(PciIo)) { + //set data transfer with default + Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth); + } return EFI_SUCCESS; } } while (++Retry < 40); @@ -879,9 +901,53 @@ EmmcSwitchToHS200 ( return Status; } - Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode->DriverStrength, BusMode->BusTiming, BusMode->ClockFreq); - if (EFI_ERROR (Status)) { - return Status; + if (BhtHostPciSupport(PciIo)){ + BusMode->BusTiming = SdMmcMmcHs200; + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode->DriverStrength, + BusMode->BusTiming, BusMode->ClockFreq); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SdMmcHcWaitMmioSet ( + PciIo, + Slot, + 0x1cc, + sizeof (Rca), + BIT14, + BIT14, + SD_MMC_HC_GENERIC_TIMEOUT + ); + if (EFI_ERROR (Status)) { + return Status; + } + + //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time + UINT32 value32; + while (1) { + Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32); + if (((value32 >> 18) & 0x01) == ((value32 >> 16) & 0x01)) { + break; + } + } + + Status = SdMmcHcWaitMmioSet ( + PciIo, + Slot, + 0x1cc, + sizeof (Rca), + BIT11, + BIT11, + SD_MMC_CLOCK_STABLE_TIMEOUT + ); + if (EFI_ERROR(Status)) { + return Status; + } + } else { + Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode->DriverStrength, BusMode->BusTiming, BusMode->ClockFreq); + if (EFI_ERROR (Status)) { + return Status; + } } Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusMode->BusWidth); @@ -1283,10 +1349,89 @@ EmmcSetBusMode ( BusMode.DriverStrength.Emmc )); + if (BhtHostPciSupport(PciIo)) { + UINT8 EmmcVar; + UINTN EmmcVarSize; + Status = gRT->GetVariable ( + L"EMMC_FORCE_CARD_MODE", + &gEfiGenericVariableGuid, + NULL, + &EmmcVarSize, + &EmmcVar + ); + if (!EFI_ERROR(Status) && EmmcVar <= 2) { + if (EmmcVar == 2) { + BusMode.BusTiming = SdMmcMmcHs200; + BusMode.ClockFreq = 200; + } else if (EmmcVar == 1) { + BusMode.BusTiming = SdMmcMmcHs200; + BusMode.ClockFreq = 100; + } else { + BusMode.BusTiming = SdMmcMmcHsSdr; + BusMode.ClockFreq = 52; + } + } else { + BusMode.BusTiming = SdMmcMmcHsSdr; + BusMode.ClockFreq = 52; + } + } + if (BusMode.BusTiming == SdMmcMmcHs400) { + // + // Execute HS400 timing switch procedure + // Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, &BusMode); } else if (BusMode.BusTiming == SdMmcMmcHs200) { + // + // Execute HS200 timing switch procedure + // Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, &BusMode); + + if (EFI_ERROR(Status)) { + if (BhtHostPciSupport(PciIo)) { + UINT32 val32; + UINT16 EmmcVar; + UINTN EmmcVarSize; +#if !defined(HS100_ALLPASS_PHASE) || HS100_ALLPASS_PHASE > 10 || HS100_ALLPASS_PHASE < 0 +#error "HS100_ALLPASS_PHASE is undefined or value is invalid" +#else + val32 = PciBhtRead32(PciIo, 0x300); + val32 &= 0xFF0FFFFF; + EmmcVarSize = sizeof(EmmcVar); + Status = gRT->GetVariable ( + L"EMMC_HS100_ALLPASS_PHASE", + &gEfiGenericVariableGuid, + NULL, + &EmmcVarSize, + &EmmcVar + ); + if (EFI_ERROR(Status) || EmmcVar > 10) + EmmcVar = HS100_ALLPASS_PHASE; + val32 |= (EmmcVar << 20); + PciBhtWrite32(PciIo, 0x300, 0x21000033 | val32); +#endif + BusMode.ClockFreq = 100; + + SdMmcHcRwMmio (PciIo, Slot, 0x3C, TRUE, sizeof(val32), &val32); + val32 &= ~BIT22; + SdMmcHcRwMmio (PciIo, Slot, 0x3C, FALSE, sizeof(val32), &val32); + val32 = (BIT26 | BIT25); + SdMmcHcOrMmio (PciIo, Slot, 0x2C, sizeof(val32), &val32); + + Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, &BusMode); + if (EFI_ERROR(Status)) { + if (((ExtCsd.DeviceType & BIT1) != 0) && (Private->Capability[Slot].HighSpeed != 0)) { + BusMode.BusTiming = SdMmcMmcHsSdr; + BusMode.ClockFreq = 52; + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, &BusMode); + } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private->Capability[Slot].HighSpeed != 0)) { + BusMode.BusTiming = SdMmcMmcHsSdr; + BusMode.ClockFreq = 26; + Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, &BusMode); + } + } + } + } } else { // // Note that EmmcSwitchToHighSpeed is also called for SdMmcMmcLegacy @@ -1326,10 +1471,18 @@ EmmcIdentification ( UINT32 Ocr; UINT16 Rca; UINTN Retry; + UINT32 val32; PciIo = Private->PciIo; PassThru = &Private->PassThru; + if (BhtHostPciSupport(PciIo)) { + /* Clear clk src selection before reset */ + val32 = PciBhtRead32(PciIo, BHT_CLK_SRC_SWITCH); + val32 &= ~BHT_PCR_SD_SEL_DLL; + PciBhtWrite32(PciIo, BHT_CLK_SRC_SWITCH, val32); + } + Status = EmmcReset (PassThru, Slot); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd0 fails with %r\n", Status)); diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c index 8496ce472768..65f4ad8f3ab3 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c @@ -313,6 +313,13 @@ SdMmcPciHcEnumerateDevice ( continue; } + if (BhtHostPciSupport(Private->PciIo)) { + Status = SdMmcHcGetCapability (Private->PciIo, Slot, &Private->Capability[Slot]); + if (EFI_ERROR (Status)) { + continue; + } + } + Private->Slot[Slot].MediaPresent = TRUE; Private->Slot[Slot].Initialized = TRUE; RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE); @@ -330,6 +337,7 @@ SdMmcPciHcEnumerateDevice ( // This card doesn't get initialized correctly. // if (Index == RoutineNum) { + DEBUG ((DEBUG_INFO, "Load driver failure\n")); Private->Slot[Slot].Initialized = FALSE; } @@ -553,6 +561,8 @@ SdMmcPciHcDriverBindingStart ( UINT32 RoutineNum; BOOLEAN MediaPresent; BOOLEAN Support64BitDma; + UINT16 IntStatus; + UINT32 value; DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n")); @@ -759,6 +769,13 @@ SdMmcPciHcDriverBindingStart ( continue; } + if (BhtHostPciSupport(PciIo)) { + Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]); + if (EFI_ERROR (Status)) { + continue; + } + } + Private->Slot[Slot].MediaPresent = TRUE; Private->Slot[Slot].Initialized = TRUE; RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE); @@ -776,9 +793,25 @@ SdMmcPciHcDriverBindingStart ( // This card doesn't get initialized correctly. // if (Index == RoutineNum) { + DEBUG ((DEBUG_INFO, "Load driver failure\n")); Private->Slot[Slot].Initialized = FALSE; } } + if (BhtHostPciSupport(Private->PciIo)) { + SdMmcHcRwMmio (Private->PciIo,0,0x110,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,0x114,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,0x1a8,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,0x1ac,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,0x1B0,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,0x1CC,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,0x040,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_PRESENT_STATE,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_HOST_CTRL1,TRUE,sizeof (IntStatus),&IntStatus); + SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_CLOCK_CTRL,TRUE,sizeof (IntStatus),&IntStatus); + SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_TIMEOUT_CTRL,TRUE,sizeof (IntStatus),&IntStatus); + SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_NOR_INT_STS,TRUE,sizeof (value),&value); + SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_HOST_CTRL2,TRUE,sizeof (IntStatus),&IntStatus); + } // // Enable 64-bit DMA support in the PCI layer if this controller diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h index b76c7cffa279..0f3b63bfb276 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h @@ -20,6 +20,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include #include @@ -34,6 +35,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include +#include + #include "SdMmcPciHci.h" extern EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciHcComponentName; @@ -47,10 +50,16 @@ extern EDKII_SD_MMC_OVERRIDE *mOverride; #define SD_MMC_HC_PRIVATE_FROM_THIS(a) \ CR(a, SD_MMC_HC_PRIVATE_DATA, PassThru, SD_MMC_HC_PRIVATE_SIGNATURE) +#define HOST_CLK_DRIVE_STRENGTH 2 +#define HOST_DAT_DRIVE_STRENGTH 2 +#define HS200_ALLPASS_PHASE 0 +#define HS100_ALLPASS_PHASE 6 + // // Generic time out value, 1 microsecond as unit. // #define SD_MMC_HC_GENERIC_TIMEOUT (PcdGet32 (PcdSdMmcGenericTimeoutValue)) +#define SD_MMC_CLOCK_STABLE_TIMEOUT 3 * 1000 // // SD/MMC async transfer timer interval, set by experience. diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf index e502443ddd5b..8b9c5e2f6c80 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf @@ -14,12 +14,12 @@ ## [Defines] - INF_VERSION = 0x00010005 + INF_VERSION = 0x00010007 BASE_NAME = SdMmcPciHcDxe MODULE_UNI_FILE = SdMmcPciHcDxe.uni FILE_GUID = 8E325979-3FE1-4927-AAE2-8F5C4BD2AF0D MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 + VERSION_STRING = 1.5.4 ENTRY_POINT = InitializeSdMmcPciHcDxe # @@ -64,6 +64,9 @@ gEfiPciIoProtocolGuid ## TO_START gEfiSdMmcPassThruProtocolGuid ## BY_START +[Guids] + gEfiGenericVariableGuid + # [Event] # EVENT_TYPE_PERIODIC_TIMER ## SOMETIMES_CONSUMES diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c index 9e8a7f4e436d..fb2b4fa44b53 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c @@ -15,6 +15,9 @@ #include "SdMmcPciHcDxe.h" +int g_deviceId = 0; + + /** Dump the content of SD/MMC host controller's Capability Register. @@ -1171,6 +1174,15 @@ SdMmcHcInitPowerVoltage ( // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register // Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage); + if (BhtHostPciSupport(PciIo)){ + // 1.8V signaling enable + HostCtrl2 = BIT3; + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2); + gBS->Stall (5000); + if (EFI_ERROR (Status)) { + return Status; + } + } return Status; } @@ -1222,8 +1234,8 @@ SdMmcHcInitHost ( EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; SD_MMC_HC_SLOT_CAP Capability; + UINT32 value32; - // // Notify the SD/MMC override protocol that we are about to initialize // the SD/MMC host controller. // @@ -1248,9 +1260,191 @@ SdMmcHcInitHost ( PciIo = Private->PciIo; Capability = Private->Capability[Slot]; - Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]); - if (EFI_ERROR (Status)) { - return Status; + if (BhtHostPciSupport(PciIo)){ + UINT8 CardMode; + UINT16 EmmcVar; + UINTN EmmcVarSize; + UINT64 Cap; + + //unlock PCR write protect +#ifdef DISABLE_L1_2 + PciBhtAnd32(PciIo, 0xd0, ~(BIT31)); + PciBhtAnd32(PciIo, 0x90, ~(BIT1 | BIT0)); + + value32 = PciBhtRead32(PciIo, 0xe0); + value32 &= ~(BIT31 | BIT30 | BIT29 | BIT28); + value32 |= (BIT29 | BIT28); + PciBhtWrite32(PciIo, 0xe0, value32); + + value32 = PciBhtRead32(PciIo, 0xfc); + value32 &= ~(BIT19 | BIT18 | BIT17 | BIT16); + value32 |= (BIT19); + PciBhtWrite32(PciIo, 0xfc, value32); + + value32 = PciBhtRead32(PciIo, 0x3f4); + value32 &= ~(BIT3 | BIT2 | BIT1 | BIT0); + value32 |= (BIT3 | BIT1); + PciBhtWrite32(PciIo, 0x3f4, value32); + + value32 = PciBhtRead32(PciIo, 0x248); + value32 &= ~(BIT3 | BIT2 | BIT1 | BIT0); + value32 |= (BIT3 | BIT1); + PciBhtWrite32(PciIo, 0x248, value32); + + value32 = PciBhtRead32(PciIo, 0x90); + value32 &= ~(BIT1 | BIT0); + value32 |= (BIT1); + PciBhtWrite32(PciIo, 0x90, value32); +#endif + + /* FET on */ + PciBhtOr32(PciIo, 0xEC, 0x3); + /* Led on */ + //PciBhtAnd32(PciIo, 0x334, (UINT32)~BIT13); + PciBhtOr32(PciIo, 0xD4, BIT6); + /* Set 1.8v emmc signaling flag */ + PciBhtOr32(PciIo, 0x308, BIT4); + /* Set 200MBaseClock */ + value32 = PciBhtRead32(PciIo, 0x304); + value32 &= 0x0000FFFF; + value32 |= 0x25100000; +#if !defined(HOST_CLK_DRIVE_STRENGTH) || HOST_CLK_DRIVE_STRENGTH > 7 || HOST_CLK_DRIVE_STRENGTH < 0 +#error "HOST_CMD_DRIVE_STRENGTH is undefined or value is invalid" +#else + EmmcVarSize = sizeof(EmmcVar); + Status = gRT->GetVariable ( + L"EMMC_CLK_DRIVER_STRENGTH", + &gEfiGenericVariableGuid, + NULL, + &EmmcVarSize, + &EmmcVar + ); + if (EFI_ERROR(Status)) { + EmmcVar = HOST_CLK_DRIVE_STRENGTH; + } + value32 &= 0xFFFFFF8F; + value32 |= ((EmmcVar & 0x7) << 4); +#endif +#if !defined(HOST_DAT_DRIVE_STRENGTH) || HOST_DAT_DRIVE_STRENGTH > 7 || HOST_DAT_DRIVE_STRENGTH < 0 +#error "HOST_DATA_DRIVE_STRENGTH is undefined or value is invalid" +#else + EmmcVarSize = sizeof(EmmcVar); + Status = gRT->GetVariable ( + L"EMMC_DATA_DRIVER_STRENGTH", + &gEfiGenericVariableGuid, + NULL, + &EmmcVarSize, + &EmmcVar + ); + if (EFI_ERROR(Status)) { + EmmcVar = HOST_DAT_DRIVE_STRENGTH; + } + value32 &= 0xFFFFFFF1; + value32 |= ((EmmcVar & 0x7) << 1); +#endif + PciBhtWrite32(PciIo, 0x304, value32); + PciBhtOr32(PciIo, 0x3E4, BIT22); + + EmmcVarSize = sizeof(CardMode); + Status = gRT->GetVariable ( + L"EMMC_FORCE_CARD_MODE", + &gEfiGenericVariableGuid, + NULL, + &EmmcVarSize, + &CardMode + ); + if (EFI_ERROR(Status) || CardMode > 2) { + CardMode = 0; + } + + if (CardMode == 1) { +#if !defined(HS100_ALLPASS_PHASE) || HS100_ALLPASS_PHASE > 10 || HS100_ALLPASS_PHASE < 0 +#error "HS200_ALLPASS_PHASE is undefined or value is invalid" +#else + EmmcVarSize = sizeof(EmmcVar); + Status = gRT->GetVariable ( + L"EMMC_HS100_ALLPASS_PHASE", + &gEfiGenericVariableGuid, + NULL, + &EmmcVarSize, + &EmmcVar + ); + if (EFI_ERROR(Status) || EmmcVar > 10) { + EmmcVar = HS100_ALLPASS_PHASE; + } +#endif + } else if (CardMode == 2) { +#if !defined(HS200_ALLPASS_PHASE) || HS200_ALLPASS_PHASE > 10 || HS200_ALLPASS_PHASE < 0 +#error "HS200_ALLPASS_PHASE is undefined or value is invalid" +#else + EmmcVarSize = sizeof(EmmcVar); + Status = gRT->GetVariable ( + L"EMMC_HS200_ALLPASS_PHASE", + &gEfiGenericVariableGuid, + NULL, + &EmmcVarSize, + &EmmcVar + ); + if (EFI_ERROR(Status) || EmmcVar > 10) { + EmmcVar = HS200_ALLPASS_PHASE; + } +#endif + } + + value32 = 0x21000033 | (EmmcVar << 20); + PciBhtWrite32(PciIo, 0x300, value32); + + //enable internal clk + value32 = BIT0; + Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,sizeof(value32), &value32); + + //reset pll start + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); + value32 |= BIT12; + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32); + gBS->Stall(1); + + //reset pll end + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE,sizeof(value32), &value32); + value32 &= ~BIT12; + value32 |= BIT18; + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32); + + //wait BaseClk stable 0x1CC bit14 + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); + while(!(value32&BIT14)){ + gBS->Stall(100); + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); + } + + if (value32 & BIT18) { + //Wait 2nd Card Detect debounce Finished by wait twice of debounce max time + while (1) { + Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32); + if (((value32 >> 16) & 0x01) == ((value32 >> 18) & 0x01)) + break; + } + //force pll active end + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32); + value32 &= ~BIT18; + Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32); + } + + Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CAP, TRUE, sizeof (Cap), &Cap); + if (EFI_ERROR (Status)) { + return Status; + } + CopyMem (&Capability, &Cap, sizeof (Cap)); + + Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Status = SdMmcHcInitV4Enhancements (PciIo, Slot, Capability, Private->ControllerVersion[Slot]); + if (EFI_ERROR (Status)) { + return Status; + } } // @@ -1265,9 +1459,11 @@ SdMmcHcInitHost ( return Status; } - Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability); - if (EFI_ERROR (Status)) { - return Status; + if (!BhtHostPciSupport(PciIo)){ + Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability); + if (EFI_ERROR (Status)) { + return Status; + } } Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot); @@ -2929,3 +3125,280 @@ SdMmcWaitTrbResult ( return EFI_TIMEOUT; } + +BOOLEAN BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo) +{ + PCI_TYPE00 Pci; + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, + 0, sizeof Pci / sizeof (UINT32), &Pci); + + DEBUG ((DEBUG_INFO, "check device %04x:%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId)); + + if (Pci.Hdr.VendorId != 0x1217) + goto end; + + switch (Pci.Hdr.DeviceId) + { + case 0x8420: //PCI_DEV_ID_SDS0 + case 0x8421: //PCI_DEV_ID_SDS1 + case 0x8520: //PCI_DEV_ID_FJ2 + case 0x8620: //PCI_DEV_ID_SB0 + case 0x8621: //PCI_DEV_ID_SB1 + g_deviceId = Pci.Hdr.DeviceId; + return 1; + default: + break; + } + + end: + return 0; +} + +void DbgNull(IN CONST CHAR16 * fmt, ...) +{ +} + +UINT32 bht_readl(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset) +{ + UINT32 arg; + PciIo->Mem.Read(PciIo,EfiPciIoWidthUint32,1,offset,1,&arg); + return arg; +} + +void bht_writel(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) +{ + PciIo->Mem.Write(PciIo,EfiPciIoWidthUint32,1,offset,1,&value); +} + + +UINT32 PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset) +{ + UINT32 i = 0; + UINT32 tmp[3] = {0}; + + if((g_deviceId == PCI_DEV_ID_SDS0) || + (g_deviceId == PCI_DEV_ID_SDS1) || + (g_deviceId == PCI_DEV_ID_FJ2) || + (g_deviceId == PCI_DEV_ID_SB0) || + (g_deviceId == PCI_DEV_ID_SB1)) + { + // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg. + // Enable mapping + + // Check function conflict + if((g_deviceId == PCI_DEV_ID_SDS0) || + (g_deviceId == PCI_DEV_ID_FJ2) || + (g_deviceId == PCI_DEV_ID_SB0) || + (g_deviceId == PCI_DEV_ID_SB1)) + { + i = 0; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); + while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0) + { + if(i == 5) + { + goto RD_DIS_MAPPING; + } + gBS->Stall(1000); + i++; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); + + } + } + else if(g_deviceId == PCI_DEV_ID_SDS1) + { + i = 0; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); + while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - %s() function 1 can't lock!\n", __FUNCTION__)); + goto RD_DIS_MAPPING; + } + gBS->Stall(1000); + i++; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); + } + } + + // Check last operation is complete + i = 0; + while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - [204] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingCtl))); + //DbgErr((DRIVERNAME " - [208] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingEn))); + //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__)); + goto RD_DIS_MAPPING; + } + gBS->Stall(1000); + i += 1; + } + + // Set register address + tmp[0] |= 0x40000000; + tmp[0] |= offset; + bht_writel(PciIo, BHT_PCIRMappingCtl, tmp[0]); + + // Check read is complete + i = 0; + while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x40000000) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - %s() check read operation complete timeout!!!\n", __FUNCTION__)); + goto RD_DIS_MAPPING; + } + gBS->Stall(1000); + i += 1; + } + + // Get PCIR value + tmp[1] = bht_readl(PciIo, BHT_PCIRMappingVal); + +RD_DIS_MAPPING: + // Disable mapping + bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000); + + //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[1]); + return tmp[1]; + } + + //DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[0]); + return tmp[0]; +} + +void PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) +{ + UINT32 tmp = 0; + UINT32 i = 0; + + if((g_deviceId == PCI_DEV_ID_SDS0) || + (g_deviceId == PCI_DEV_ID_SDS1) || + (g_deviceId == PCI_DEV_ID_FJ2) || + (g_deviceId == PCI_DEV_ID_SB0) || + (g_deviceId == PCI_DEV_ID_SB1)) + { + // For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg. + // Upper caller doesn't need to set 0xD0. + + // Enable mapping + + // Check function conflict + if((g_deviceId == PCI_DEV_ID_SDS0) || + (g_deviceId == PCI_DEV_ID_FJ2) || + (g_deviceId == PCI_DEV_ID_SB0) || + (g_deviceId == PCI_DEV_ID_SB1)) + { + i = 0; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); + while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__)); + goto WR_DIS_MAPPING; + } + + gBS->Stall(1000); + i++; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000); + } + } + else if(g_deviceId == PCI_DEV_ID_SDS1) + { + i = 0; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); + + while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__)); + goto WR_DIS_MAPPING; + } + + gBS->Stall(1000); + i++; + bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000); + } + } + + // Enable MEM access + bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000000); + bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0); + + // Check last operation is complete + i = 0; + while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__)); + goto WR_DIS_MAPPING; + } + gBS->Stall(1000); + i += 1; + } + + // Set write value + bht_writel(PciIo, BHT_PCIRMappingVal, value); + // Set register address + tmp |= 0x80000000; + tmp |= offset; + bht_writel(PciIo, BHT_PCIRMappingCtl, tmp); + + // Check write is complete + i = 0; + while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x80000000) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - %s() check write operation complete timeout!!!\n", __FUNCTION__)); + goto WR_DIS_MAPPING; + } + gBS->Stall(1000); + i += 1; + } + +WR_DIS_MAPPING: + // Disable MEM access + bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000001); + bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0); + + // Check last operation is complete + i = 0; + while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000) + { + if(i == 5) + { + //DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__)); + break; + } + gBS->Stall(1000); + i += 1; + } + + // Disable function conflict + + // Disable mapping + bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000); + } +} + +void PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) +{ + UINT32 arg; + arg = PciBhtRead32(PciIo, offset); + PciBhtWrite32(PciIo, offset, value | arg); +} + +void PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value) +{ + UINT32 arg; + arg = PciBhtRead32(PciIo, offset); + PciBhtWrite32(PciIo, offset, value & arg); +} diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h index e436a7d11a1e..2371d50f2589 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h @@ -613,4 +613,35 @@ SdMmcSetDriverStrength ( IN SD_DRIVER_STRENGTH_TYPE DriverStrength ); +BOOLEAN +BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo); +UINT32 +PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset); +void +PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value); +void +PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value); +void +PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value); +extern void +DbgNull(IN CONST CHAR16 * fmt, ...); + + +#define PCI_DEV_ID_RJ 0x8320 +#define PCI_DEV_ID_SDS0 0x8420 +#define PCI_DEV_ID_SDS1 0x8421 +#define PCI_DEV_ID_FJ2 0x8520 +#define PCI_DEV_ID_SB0 0x8620 +#define PCI_DEV_ID_SB1 0x8621 + + +// O2/BHT add BAR1 for PCIR mapping registers +// These registers is defined by O2/BHT, but we may follow name definition rule. +#define BHT_PCIRMappingVal (0x200) /* PCI CFG Space Register Mapping Value Register */ +#define BHT_PCIRMappingCtl (0x204) /* PCI CFG Space Register Mapping Control Register */ +#define BHT_PCIRMappingEn (0x208) /* PCI CFG Space Register Mapping Enable Register */ +#define BHT_GPIOCTL (0x210) /* GPIO control register*/ +#define BHT_CLK_SRC_SWITCH (0x354) /* PCI CFG Space Register */ +#define BHT_PCR_SD_SEL_DLL (1 << 16) + #endif diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c index c337f15118d2..a4c126c6d5b3 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c @@ -817,8 +817,9 @@ XhcTransfer ( ASSERT (Urb->Result == EFI_USB_NOERROR); Status = EFI_SUCCESS; DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: pending URB is finished, Length = %d.\n", Type, Urb->Completed)); - } else if (EFI_ERROR (RecoveryStatus)) { - DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed!\n", Type)); + } else if (EFI_ERROR(RecoveryStatus)) { + DEBUG((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed!\n", Type)); + Status = RecoveryStatus; } } diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c index 52551a370900..23464ef0cf0c 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c @@ -1285,6 +1285,36 @@ XhcCheckUrbResult ( return Urb->Finished; } +STATIC +BOOLEAN +EFIAPI +XhcEndpointRunning ( + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 Dci + ) +{ + DEVICE_CONTEXT *OutputContext; + + OutputContext = Xhc->UsbDevContext[SlotId].OutputContext; + return OutputContext && OutputContext->EP[Dci -1].EPState == 1; +} + +STATIC +BOOLEAN +EFIAPI +XhcEndpointHalted ( + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 Dci + ) +{ + DEVICE_CONTEXT *OutputContext; + + OutputContext = Xhc->UsbDevContext[SlotId].OutputContext; + return OutputContext && OutputContext->EP[Dci -1].EPState == 2; +} + /** Execute the transfer by polling the URB. This is a synchronous operation. @@ -1333,6 +1363,10 @@ XhcExecTransfer ( ASSERT (Dci < 32); } + if (!CmdTransfer && XhcEndpointHalted(Xhc, SlotId, Dci)) { + goto DONE; + } + if (Timeout == 0) { IndefiniteTimeout = TRUE; } @@ -1363,9 +1397,15 @@ XhcExecTransfer ( ElapsedTicks += TicksDelta; } while (IndefiniteTimeout || ElapsedTicks < TimeoutTicks); +DONE: if (!Finished) { - Urb->Result = EFI_USB_ERR_TIMEOUT; - Status = EFI_TIMEOUT; + if (XhcEndpointHalted(Xhc, SlotId, Dci)) { + Urb->Result = EFI_USB_ERR_STALL; + Status = EFI_DEVICE_ERROR; + } else { + Urb->Result = EFI_USB_ERR_TIMEOUT; + Status = EFI_TIMEOUT; + } } else if (Urb->Result != EFI_USB_NOERROR) { Status = EFI_DEVICE_ERROR; } @@ -3476,6 +3516,19 @@ XhcStopEndpoint ( EvtTrb = NULL; + if (XhcEndpointHalted(Xhc, SlotId, Dci)) { + if (PendingUrb != NULL) { + PendingUrb->Result = EFI_USB_ERR_STALL; + } + return EFI_DEVICE_ERROR; + } + if (!XhcEndpointRunning(Xhc, SlotId, Dci)) { + if (PendingUrb != NULL) { + PendingUrb->Result = EFI_USB_ERR_SYSTEM; + } + return EFI_DEVICE_ERROR; + } + // // When XhcCheckUrbResult waits for the Stop_Endpoint completion, it also checks // the PendingUrb completion status, because it's possible that the PendingUrb is diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c b/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c index 93608637dfcd..eba842f8cb28 100644 --- a/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c +++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c @@ -808,10 +808,6 @@ InitUSBKeyboard ( IN OUT USB_KB_DEV *UsbKeyboardDevice ) { - UINT16 ConfigValue; - EFI_STATUS Status; - UINT32 TransferResult; - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST), @@ -822,41 +818,6 @@ InitUSBKeyboard ( InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA)); InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA)); - // - // Use the config out of the descriptor - // Assumed the first config is the correct one and this is not always the case - // - Status = UsbGetConfiguration ( - UsbKeyboardDevice->UsbIo, - &ConfigValue, - &TransferResult - ); - if (EFI_ERROR (Status)) { - ConfigValue = 0x01; - // - // Uses default configuration to configure the USB Keyboard device. - // - Status = UsbSetConfiguration ( - UsbKeyboardDevice->UsbIo, - ConfigValue, - &TransferResult - ); - if (EFI_ERROR (Status)) { - // - // If configuration could not be set here, it means - // the keyboard interface has some errors and could - // not be initialized - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR), - UsbKeyboardDevice->DevicePath - ); - - return EFI_DEVICE_ERROR; - } - } - // // Set boot protocol for the USB Keyboard. // This driver only supports boot protocol. diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c index 8c09831f56fa..42d4f277abba 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c @@ -281,7 +281,7 @@ UsbBootExecCmdWithRetry ( DataLen, Timeout ); - if ((Status == EFI_SUCCESS) || (Status == EFI_NO_MEDIA)) { + if (Status == EFI_SUCCESS || Status == EFI_NO_MEDIA || Status == EFI_DEVICE_ERROR) { break; } diff --git a/MdeModulePkg/Include/Library/BootLogoLib.h b/MdeModulePkg/Include/Library/BootLogoLib.h index a2fd667026f5..f99b9c2dd255 100644 --- a/MdeModulePkg/Include/Library/BootLogoLib.h +++ b/MdeModulePkg/Include/Library/BootLogoLib.h @@ -60,4 +60,17 @@ BootLogoUpdateProgress ( IN UINTN PreviousValue ); +/** + + Clear progress bar and title above it. It only works in Graphics mode. + + @retval EFI_STATUS Successly clear the progress bar + +**/ +EFI_STATUS +EFIAPI +BootLogoClearProgress ( + VOID + ); + #endif diff --git a/MdeModulePkg/Include/Protocol/PlatformLogo.h b/MdeModulePkg/Include/Protocol/PlatformLogo.h index 08e1dc35a419..7c9ef63c66dd 100644 --- a/MdeModulePkg/Include/Protocol/PlatformLogo.h +++ b/MdeModulePkg/Include/Protocol/PlatformLogo.h @@ -29,7 +29,8 @@ typedef enum { EdkiiPlatformLogoDisplayAttributeCenterBottom, EdkiiPlatformLogoDisplayAttributeLeftBottom, EdkiiPlatformLogoDisplayAttributeCenterLeft, - EdkiiPlatformLogoDisplayAttributeCenter + EdkiiPlatformLogoDisplayAttributeCenter, + EdkiiPlatformLogoDisplayAttributeBGRTSpecification } EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE; /** diff --git a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c index 5beb0e0aa547..1b2aa201e955 100644 --- a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c +++ b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c @@ -145,7 +145,6 @@ BootLogoEnableLogo ( DestX = SizeOfX - Image.Width; DestY = 0; break; - case EdkiiPlatformLogoDisplayAttributeCenterLeft: DestX = 0; DestY = (SizeOfY - Image.Height) / 2; @@ -158,7 +157,6 @@ BootLogoEnableLogo ( DestX = SizeOfX - Image.Width; DestY = (SizeOfY - Image.Height) / 2; break; - case EdkiiPlatformLogoDisplayAttributeLeftBottom: DestX = 0; DestY = SizeOfY - Image.Height; @@ -171,7 +169,10 @@ BootLogoEnableLogo ( DestX = SizeOfX - Image.Width; DestY = SizeOfY - Image.Height; break; - + case EdkiiPlatformLogoDisplayAttributeBGRTSpecification: + DestX = (SizeOfX - Image.Width) / 2; + DestY = (SizeOfY * 382) / 1000 - Image.Height / 2; + break; default: ASSERT (FALSE); continue; @@ -435,3 +436,56 @@ BootLogoUpdateProgress ( return EFI_SUCCESS; } + +/** + + Clear progress bar and title above it. It only works in Graphics mode. + + @retval EFI_STATUS Successly clear the progress bar + +**/ +EFI_STATUS +EFIAPI +BootLogoClearProgress ( + VOID + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + UINT32 SizeOfX; + UINT32 SizeOfY; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + UINTN PosY; + + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; + SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; + + PosY = SizeOfY * 48 / 50; + + // + // Clear progress area + // + SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0); + + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &Color, + EfiBltVideoFill, + 0, + 0, + 0, + PosY - EFI_GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1), + SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf index 03fd70451bc6..9020f753379a 100644 --- a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf +++ b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf @@ -46,3 +46,6 @@ gEdkiiBootLogo2ProtocolGuid ## SOMETIMES_CONSUMES gEfiUserManagerProtocolGuid ## CONSUMES gEdkiiPlatformLogoProtocolGuid ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFollowBGRTSpecification ## CONSUMES diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c index 19751642a30c..aff466cb6e7d 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c @@ -1527,20 +1527,6 @@ InitializeBmmConfig ( // GetBootOrder (CallbackData); - // - // Initialize data which located in Driver Options Menu - // - GetDriverOrder (CallbackData); - - // - // Initialize data which located in Console Options Menu - // - GetConsoleOutMode (CallbackData); - GetConsoleInCheck (CallbackData); - GetConsoleOutCheck (CallbackData); - GetConsoleErrCheck (CallbackData); - GetTerminalAttribute (CallbackData); - CallbackData->BmmFakeNvData.ForceReconnect = TRUE; // diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr index 69fb60632464..38ab6f4cee95 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr @@ -42,63 +42,6 @@ formset endform; - form formid = FORM_BOOT_SETUP_ID, - title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_BOOT_SETUP_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_ADD_ID; - - goto FORM_BOOT_DEL_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_DEL_ID; - - goto FORM_BOOT_CHG_ID, - prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), - help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP), - flags = INTERACTIVE, - key = FORM_BOOT_CHG_ID; - endform; - - form formid = FORM_DRIVER_SETUP_ID, - title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //help = STRING_TOKEN(STR_FORM_GOTO_MAIN), - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_DRV_ADD_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE), - help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP), - flags = INTERACTIVE, - key = FORM_DRV_ADD_ID; - - goto FORM_DRV_DEL_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE), - help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_DRV_DEL_ID; - - goto FORM_DRV_CHG_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), - help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), - flags = INTERACTIVE, - key = FORM_DRV_CHG_ID; - endform; - form formid = FORM_BOOT_ADD_ID, title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE); @@ -156,199 +99,4 @@ formset endform; - form formid = FORM_DRV_ADD_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_DRIVER_SETUP_ID, - prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), - help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), - flags = INTERACTIVE, - key = FORM_DRV_ADD_FILE_ID; - - endform; - - form formid = FORM_DRV_ADD_FILE_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); - - label FORM_DRV_ADD_FILE_ID; - label LABEL_END; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - string varid = BmmData.DriverDescriptionData, - questionid = KEY_VALUE_DRIVER_DESCRIPTION, - prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - minsize = 6, - maxsize = 75, - endstring; - - string varid = BmmData.DriverOptionalData, - questionid = KEY_VALUE_DRIVER_OPTION, - prompt = STRING_TOKEN(STR_OPTIONAL_DATA), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - minsize = 0, - maxsize = 120, - endstring; - - checkbox varid = BmmData.ForceReconnect, - prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), - help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), - flags = CHECKBOX_DEFAULT, - key = 0, - endcheckbox; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - text - help = STRING_TOKEN(STR_SAVE_AND_EXIT), - text = STRING_TOKEN(STR_SAVE_AND_EXIT), - flags = INTERACTIVE, - key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset??? - - text - help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), - text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), - flags = INTERACTIVE, - key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER; - endform; - - form formid = FORM_DRV_DEL_ID, - title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE); - - label FORM_DRV_DEL_ID; - label LABEL_END; - - endform; - - form formid = FORM_DRV_CHG_ID, - title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE); - - label FORM_DRV_CHG_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_MAIN_ID, - title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE); - - goto FORM_MAIN_ID, - prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), - help = STRING_TOKEN(STR_FORM_GOTO_MAIN); - //flags = INTERACTIVE, - //key = FORM_MAIN_ID; - - goto FORM_CON_IN_ID, - prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE), - help = STRING_TOKEN(STR_FORM_CON_IN_HELP), - flags = INTERACTIVE, - key = FORM_CON_IN_ID; - - goto FORM_CON_OUT_ID, - prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE), - help = STRING_TOKEN(STR_FORM_CON_OUT_HELP), - flags = INTERACTIVE, - key = FORM_CON_OUT_ID; - - goto FORM_CON_ERR_ID, - prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE), - help = STRING_TOKEN(STR_FORM_STD_ERR_HELP), - flags = INTERACTIVE, - key = FORM_CON_ERR_ID; - - goto FORM_CON_MODE_ID, - prompt = STRING_TOKEN(STR_FORM_MODE_TITLE), - help = STRING_TOKEN(STR_FORM_MODE_HELP), - flags = INTERACTIVE, - key = FORM_CON_MODE_ID; - - goto FORM_CON_COM_ID, - prompt = STRING_TOKEN(STR_FORM_COM_TITLE), - help = STRING_TOKEN(STR_FORM_COM_HELP), - flags = INTERACTIVE, - key = FORM_CON_COM_ID; - endform; - - form formid = FORM_CON_MODE_ID, - title = STRING_TOKEN(STR_FORM_MODE_TITLE); - - label FORM_CON_MODE_ID; - label LABEL_END; - endform; - - form formid = FORM_CON_COM_ID, - title = STRING_TOKEN(STR_FORM_COM_TITLE); - - label FORM_CON_COM_ID; - label LABEL_END; - endform; - - form formid = FORM_CON_COM_SETUP_ID, - title = STRING_TOKEN(STR_CON_COM_SETUP); - - label FORM_CON_COM_SETUP_ID; - label LABEL_END; - endform; - - form formid = FORM_FILE_SEEK_ID, - title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); - - label FORM_FILE_SEEK_ID; - label LABEL_END; - endform; - - form formid = FORM_FILE_NEW_SEEK_ID, - title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); - - label FORM_FILE_NEW_SEEK_ID; - label LABEL_END; - endform; - - form formid = FORM_DRV_ADD_HANDLE_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE); - - label FORM_DRV_ADD_HANDLE_ID; - label LABEL_END; - endform; - - form formid = FORM_DRV_ADD_HANDLE_DESC_ID, - title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); - - label FORM_DRV_ADD_HANDLE_DESC_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_IN_ID, - title = STRING_TOKEN(STR_FORM_CON_IN_TITLE); - - label FORM_CON_IN_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_OUT_ID, - title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE); - - label FORM_CON_OUT_ID; - label LABEL_END; - - endform; - - form formid = FORM_CON_ERR_ID, - title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE); - - label FORM_CON_ERR_ID; - label LABEL_END; - - endform; - endformset; diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c index d79212e75ce9..4bfe3d340988 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c @@ -25,26 +25,29 @@ UiCustomizeBMMPage ( ) { // - // Create "Boot Option" menu. + // Create "Change Boot Order" menu. // - BmmCreateBootOptionMenu (HiiHandle, StartOpCodeHandle); + BmmCreateChangeBootOptionMenu(HiiHandle, StartOpCodeHandle); + // - // Create "Driver Option" menu. + // Create empty line. // - BmmCreateDriverOptionMenu (HiiHandle, StartOpCodeHandle); + BmmCreateEmptyLine (HiiHandle, StartOpCodeHandle); + // - // Create "Com Option" menu. + // Create "Add Boot Option" menu. // - BmmCreateComOptionMenu (HiiHandle, StartOpCodeHandle); + BmmCreateAddBootOptionMenu(HiiHandle, StartOpCodeHandle); + // - // Create "Boot From File" menu. + // Create empty line. // - BmmCreateBootFromFileMenu (HiiHandle, StartOpCodeHandle); + BmmCreateEmptyLine (HiiHandle, StartOpCodeHandle); // - // Find third party drivers which need to be shown in the Bmm page. + // Create "Delete Boot Option" menu. // - BmmListThirdPartyDrivers (HiiHandle, &gEfiIfrBootMaintenanceGuid, NULL, StartOpCodeHandle); + BmmCreateDeleteBootOptionMenu(HiiHandle, StartOpCodeHandle); // // Create empty line. @@ -52,13 +55,19 @@ UiCustomizeBMMPage ( BmmCreateEmptyLine (HiiHandle, StartOpCodeHandle); // - // Create "Boot Next" menu. + // Create "Boot From File" menu. + // + BmmCreateBootFromFileMenu (HiiHandle, StartOpCodeHandle); + + // + // Find third party drivers which need to be shown in the Bmm page. // - BmmCreateBootNextMenu (HiiHandle, StartOpCodeHandle); + BmmListThirdPartyDrivers (HiiHandle, &gEfiIfrBootMaintenanceGuid, NULL, StartOpCodeHandle); + // - // Create "Time Out" menu. + // Create empty line. // - BmmCreateTimeOutMenu (HiiHandle, StartOpCodeHandle); + BmmCreateEmptyLine (HiiHandle, StartOpCodeHandle); } /** diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c index e16936041a4d..fb9315cd0bdc 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c @@ -22,191 +22,76 @@ typedef struct { STATIC UI_HII_DRIVER_INSTANCE *gHiiDriverList; /** - Create the dynamic item to allow user to set the "BootNext" vaule. + Create Add Boot Option menu in the page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID -BmmCreateBootNextMenu ( - IN EFI_HII_HANDLE HiiHandle, - IN VOID *StartOpCodeHandle - ) -{ - BM_MENU_ENTRY *NewMenuEntry; - BM_LOAD_CONTEXT *NewLoadContext; - UINT16 Index; - VOID *OptionsOpCodeHandle; - UINT32 BootNextIndex; - - if (BootOptionMenu.MenuNumber == 0) { - return; - } - - BootNextIndex = NONE_BOOTNEXT_VALUE; - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { - NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); - NewLoadContext = (BM_LOAD_CONTEXT *)NewMenuEntry->VariableContext; - - if (NewLoadContext->IsBootNext) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - NewMenuEntry->DisplayStringToken, - EFI_IFR_OPTION_DEFAULT, - EFI_IFR_TYPE_NUM_SIZE_32, - Index - ); - BootNextIndex = Index; - } else { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - NewMenuEntry->DisplayStringToken, - 0, - EFI_IFR_TYPE_NUM_SIZE_32, - Index - ); - } - } - - if (BootNextIndex == NONE_BOOTNEXT_VALUE) { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - STRING_TOKEN (STR_NONE), - EFI_IFR_OPTION_DEFAULT, - EFI_IFR_TYPE_NUM_SIZE_32, - NONE_BOOTNEXT_VALUE - ); - } else { - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - STRING_TOKEN (STR_NONE), - 0, - EFI_IFR_TYPE_NUM_SIZE_32, - NONE_BOOTNEXT_VALUE - ); - } - - HiiCreateOneOfOpCode ( - StartOpCodeHandle, - (EFI_QUESTION_ID)BOOT_NEXT_QUESTION_ID, - VARSTORE_ID_BOOT_MAINT, - BOOT_NEXT_VAR_OFFSET, - STRING_TOKEN (STR_BOOT_NEXT), - STRING_TOKEN (STR_BOOT_NEXT_HELP), - 0, - EFI_IFR_NUMERIC_SIZE_4, - OptionsOpCodeHandle, - NULL - ); - - HiiFreeOpCodeHandle (OptionsOpCodeHandle); -} - -/** - Create Time Out Menu in the page. - - @param[in] HiiHandle The hii handle for the Uiapp driver. - @param[in] StartOpCodeHandle The opcode handle to save the new opcode. - -**/ -VOID -BmmCreateTimeOutMenu ( - IN EFI_HII_HANDLE HiiHandle, - IN VOID *StartOpCodeHandle - ) -{ - HiiCreateNumericOpCode ( - StartOpCodeHandle, - (EFI_QUESTION_ID)FORM_TIME_OUT_ID, - VARSTORE_ID_BOOT_MAINT, - BOOT_TIME_OUT_VAR_OFFSET, - STRING_TOKEN (STR_NUM_AUTO_BOOT), - STRING_TOKEN (STR_HLP_AUTO_BOOT), - EFI_IFR_FLAG_CALLBACK, - EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC, - 0, - 65535, - 0, - NULL - ); -} - -/** - Create Boot Option menu in the page. - - @param[in] HiiHandle The hii handle for the Uiapp driver. - @param[in] StartOpCodeHandle The opcode handle to save the new opcode. - -**/ -VOID -BmmCreateBootOptionMenu ( - IN EFI_HII_HANDLE HiiHandle, - IN VOID *StartOpCodeHandle +BmmCreateAddBootOptionMenu ( + IN EFI_HII_HANDLE HiiHandle, + IN VOID *StartOpCodeHandle ) { HiiCreateGotoOpCode ( StartOpCodeHandle, - FORM_BOOT_SETUP_ID, - STRING_TOKEN (STR_FORM_BOOT_SETUP_TITLE), - STRING_TOKEN (STR_FORM_BOOT_SETUP_HELP), + FORM_MAIN_ID, + STRING_TOKEN (STR_FORM_BOOT_ADD_TITLE), + STRING_TOKEN (STR_FORM_BOOT_IMMEDIATE_HELP), EFI_IFR_FLAG_CALLBACK, - FORM_BOOT_SETUP_ID + FORM_BOOT_ADD_ID ); } /** - Create Driver Option menu in the page. + Create Delete Boot Option menu in the page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID -BmmCreateDriverOptionMenu ( +BmmCreateDeleteBootOptionMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ) { HiiCreateGotoOpCode ( StartOpCodeHandle, - FORM_DRIVER_SETUP_ID, - STRING_TOKEN (STR_FORM_DRIVER_SETUP_TITLE), - STRING_TOKEN (STR_FORM_DRIVER_SETUP_HELP), + FORM_BOOT_DEL_ID, + STRING_TOKEN (STR_FORM_BOOT_DEL_TITLE), + STRING_TOKEN (STR_FORM_BOOT_IMMEDIATE_HELP), EFI_IFR_FLAG_CALLBACK, - FORM_DRIVER_SETUP_ID + FORM_BOOT_DEL_ID ); } /** - Create Com Option menu in the page. + Create Change Boot Option menu in the page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID -BmmCreateComOptionMenu ( +BmmCreateChangeBootOptionMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ) { HiiCreateGotoOpCode ( StartOpCodeHandle, - FORM_CON_MAIN_ID, - STRING_TOKEN (STR_FORM_CON_MAIN_TITLE), - STRING_TOKEN (STR_FORM_CON_MAIN_HELP), + FORM_BOOT_CHG_ID, + STRING_TOKEN (STR_FORM_BOOT_CHG_TITLE), + STRING_TOKEN (STR_FORM_BOOT_IMMEDIATE_HELP), EFI_IFR_FLAG_CALLBACK, - FORM_CON_MAIN_ID + FORM_BOOT_CHG_ID ); } /** - Create Com Option menu in the page. + Create Boot From File Option menu in the page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.h b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.h index dece1ec175e6..9a1c8f93d759 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.h +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.h @@ -10,72 +10,46 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define __BOOT_MAINTENANCE_MANAGER_UI_LIB_H__ /** - Create Time Out Menu in the page. + Create Add Boot option in the page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID -BmmCreateTimeOutMenu ( +BmmCreateAddBootOptionMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ); /** - Create the dynamic item to allow user to set the "BootNext" vaule. + Create Delete Boot option in the page @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID -BmmCreateBootNextMenu ( +BmmCreateDeleteBootOptionMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ); /** - Create Boot Option menu in the page. + Create Change Boot option menu in the page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID -BmmCreateBootOptionMenu ( +BmmCreateChangeBootOptionMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ); /** - Create Driver Option menu in the page. - - @param[in] HiiHandle The hii handle for the Uiapp driver. - @param[in] StartOpCodeHandle The opcode handle to save the new opcode. - -**/ -VOID -BmmCreateDriverOptionMenu ( - IN EFI_HII_HANDLE HiiHandle, - IN VOID *StartOpCodeHandle - ); - -/** - Create Com Option menu in the page. - - @param[in] HiiHandle The hii handle for the Uiapp driver. - @param[in] StartOpCodeHandle The opcode handle to save the new opcode. - -**/ -VOID -BmmCreateComOptionMenu ( - IN EFI_HII_HANDLE HiiHandle, - IN VOID *StartOpCodeHandle - ); - -/** - Create Com Option menu in the page. + Create Boot From File menu in the page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerStrings.uni b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerStrings.uni index 3d47473e6c1b..897909bf3715 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerStrings.uni +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerStrings.uni @@ -17,12 +17,12 @@ #language fr-FR "NONE" #string STR_MISSING_STRING #language en-US "Missing String" #language fr-FR "Missing String" -#string STR_FORM_MAIN_TITLE #language en-US "Boot Maintenance Manager" - #language fr-FR "Boot Maintenance Manager" +#string STR_FORM_MAIN_TITLE #language en-US "Boot Manager" + #language fr-FR "Boot Manager" #string STR_FORM_BOOT_SETUP_TITLE #language en-US "Boot Options" #language fr-FR "Boot Options" -#string STR_BOOT_MAINT_MANAGER_HELP #language en-US "This selection will take you to the Boot Maintenance Manager" - #language fr-FR "This selection will take you to the Boot Maintenance Manager" +#string STR_BOOT_MAINT_MANAGER_HELP #language en-US "Change/Add/Remove Boot Menu Entries" + #language fr-FR "Change/Add/Remove Boot Menu Entries" #string STR_FORM_BOOT_SETUP_HELP #language en-US "Modify system boot options" #language fr-FR "Modify system boot options" #string STR_FORM_DRIVER_SETUP_TITLE #language en-US "Driver Options" diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c index c2232e525b0f..2a6e435da313 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c @@ -827,7 +827,6 @@ BootManagerCallback ( { EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; UINTN BootOptionCount; - EFI_INPUT_KEY Key; if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { // @@ -872,14 +871,6 @@ BootManagerCallback ( EfiBootManagerBoot (&BootOption[QuestionId - 1]); BmSetConsoleMode (TRUE); - if (EFI_ERROR (BootOption[QuestionId - 1].Status)) { - gST->ConOut->OutputString ( - gST->ConOut, - HiiGetString (gBootManagerPrivate.HiiHandle, STRING_TOKEN (STR_ANY_KEY_CONTINUE), NULL) - ); - gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - } - EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); return EFI_SUCCESS; diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManager.h b/MdeModulePkg/Library/BootManagerUiLib/BootManager.h index 0076a9dfce20..4405a663a540 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManager.h +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManager.h @@ -46,7 +46,7 @@ typedef struct { 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \ } -#define BOOT_MANAGER_FORM_ID 0x1000 +#define BOOT_MANAGER_FORM_ID 0x1030 #define LABEL_BOOT_OPTION 0x00 #define LABEL_BOOT_OPTION_END 0x01 diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni b/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni index 2fcb9a29c50b..5f181d8f9b00 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni @@ -19,18 +19,8 @@ #langdef en-US "English" #langdef fr-FR "Français" -#string STR_BM_BANNER #language en-US "Boot Manager" - #language fr-FR "Boot Manager" -#string STR_BOOT_MANAGER_HELP #language en-US "This selection will take you to the Boot Manager" - #language fr-FR "This selection will take you to the Boot Manager" -#string STR_HELP_FOOTER #language en-US "Use the <↑> and <↓> keys to choose a boot option, the key to select a boot option, and the key to exit the Boot Manager Menu." - #language fr-FR "<↑> pour <↓> changer l'option, choisir une option, pour sortir" -#string STR_AND #language en-US " and " - #language fr-FR " et " -#string STR_BOOT_OPTION_BANNER #language en-US "Boot Manager Menu" - #language fr-FR "le Menu d'Option de Botte" -#string STR_ANY_KEY_CONTINUE #language en-US "Press any key to continue..." - #language fr-FR "Appuie n'importe quelle pour continuer..." +#string STR_BM_BANNER #language en-US "Boot Menu" +#string STR_BOOT_MANAGER_HELP #language en-US "Show One-Time Boot Menu" +#string STR_BOOT_OPTION_BANNER #language en-US "Select a Boot Device" +#string STR_ANY_KEY_CONTINUE #language en-US "Press any key to continue...\n" #string STR_LAST_STRING #language en-US "" - #language fr-FR "" - diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr b/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr index 4049fe677406..5eae056c48e7 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr @@ -8,7 +8,7 @@ //**/ #define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } -#define BOOT_MANAGER_FORM_ID 0x1000 +#define BOOT_MANAGER_FORM_ID 0x1030 #define LABEL_BOOT_OPTION 0x00 #define LABEL_BOOT_OPTION_END 0x01 @@ -27,7 +27,7 @@ formset subtitle text = STRING_TOKEN(STR_LAST_STRING); // - //Add this invisable text in order to indicate enter Boot Manager form. + //Add this invisible text in order to indicate enter Boot Manager form. // suppressif TRUE; text @@ -43,9 +43,6 @@ formset label LABEL_BOOT_OPTION; label LABEL_BOOT_OPTION_END; - subtitle text = STRING_TOKEN(STR_LAST_STRING); - subtitle text = STRING_TOKEN(STR_HELP_FOOTER); - endform; endformset; diff --git a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c index 3950bbb16922..625aba78a2d9 100644 --- a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c +++ b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c @@ -650,6 +650,9 @@ CreateDeviceManagerForm ( // if (!AddNetworkMenu) { AddNetworkMenu = TRUE; + // Always add an empty line before each entry + HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_EMPTY_STRING), 0, 0, 0); + HiiCreateGotoOpCode ( StartOpCodeHandle, NETWORK_DEVICE_LIST_FORM_ID, @@ -664,6 +667,9 @@ CreateDeviceManagerForm ( // In network device list form, same mac address device only show one menu. // while (AddItemCount > 0) { + // Always add an empty line before each entry + HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_EMPTY_STRING), 0, 0, 0); + HiiCreateGotoOpCode ( StartOpCodeHandle, NETWORK_DEVICE_FORM_ID, @@ -685,7 +691,10 @@ CreateDeviceManagerForm ( FreePool (DevicePathStr); } - HiiCreateGotoExOpCode ( + // Always add an empty line before each entry + HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_EMPTY_STRING), 0, 0, 0); + + HiiCreateGotoExOpCode ( StartOpCodeHandle, 0, Token, @@ -709,7 +718,10 @@ CreateDeviceManagerForm ( FreePool (DevicePathStr); } - HiiCreateGotoExOpCode ( + // Always add an empty line before each entry + HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_EMPTY_STRING), 0, 0, 0); + + HiiCreateGotoExOpCode ( StartOpCodeHandle, 0, Token, diff --git a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerStrings.uni b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerStrings.uni index 041cf2534475..5ef1a6b7ad59 100644 --- a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerStrings.uni +++ b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerStrings.uni @@ -12,12 +12,12 @@ #langdef en-US "English" #langdef fr-FR "Français" -#string STR_EDKII_MENU_TITLE #language en-US "Device Manager" - #language fr-FR "Device Manager" -#string STR_EDKII_MENU_HELP #language en-US "This selection will take you to the Device Manager" - #language fr-FR "This selection will take you to the Device Manager" -#string STR_DEVICES_LIST #language en-US "Devices List" - #language fr-FR "Devices List" +#string STR_EDKII_MENU_TITLE #language en-US "Advanced Configuration" + #language fr-FR "Advanced Configuration" +#string STR_EDKII_MENU_HELP #language en-US "This selection will take you to the Advanced Configuration" + #language fr-FR "This selection will take you to the Advanced Configuration" +#string STR_DEVICES_LIST #language en-US "Menu List" + #language fr-FR "Menu List" #string STR_DISK_DEVICE #language en-US "Disk Devices" #language fr-FR "Disk Devices" #string STR_VIDEO_DEVICE #language en-US "Video Devices" diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index 22ab4d7e48bc..a8c944c743e1 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -1907,6 +1907,9 @@ EfiBootManagerBoot ( UINTN FileSize; EFI_BOOT_LOGO_PROTOCOL *BootLogo; EFI_EVENT LegacyBootEvent; + EFI_INPUT_KEY Key; + UINTN Index; + UINT8 *SecureBoot; if (BootOption == NULL) { return; @@ -2047,6 +2050,40 @@ EfiBootManagerBoot ( // BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status); BootOption->Status = Status; + + if (gST->ConOut != NULL) { + // + // Clear screen + // + gST->ConOut->ClearScreen (gST->ConOut); + + AsciiPrint ( + "Booting from '%s' failed: %r\n" + "\nVerify it contains/points to a valid 64-bit UEFI OS.\n" + "\nPress any key to continue\n", + BootOption->Description, Status); + + // + // When UEFI Secure Boot is enabled, unsigned modules won't load. + // + SecureBoot = NULL; + GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL); + if ((SecureBoot != NULL) && (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) { + AsciiPrint ("SecureBoot is enabled; ensure selected boot entry is compatible.\n\n"); + FreePool (SecureBoot); + } + } + if (gST->ConIn != NULL) { + Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); + ASSERT_EFI_ERROR (Status); + ASSERT (Index == 0); + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {} + } + + if (gST->ConOut != NULL) { + gST->ConOut->ClearScreen (gST->ConOut); + } + return; } } @@ -2251,12 +2288,14 @@ BmEnumerateBootOptions ( EFI_BLOCK_IO_PROTOCOL *BlkIo; UINTN Removable; UINTN Index; + UINTN EmmcCount; CHAR16 *Description; ASSERT (BootOptionCount != NULL); *BootOptionCount = 0; BootOptions = NULL; + EmmcCount = 0; // // Parse removable block io followed by fixed block io @@ -2290,8 +2329,14 @@ BmEnumerateBootOptions ( // // Skip the fixed block io then the removable block io // - if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) { - continue; + if (FixedPcdGetBool (PcdPrioritizeInternal)) { + if (BlkIo->Media->RemovableMedia == (Removable == 0)) { + continue; + } + } else { + if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) { + continue; + } } // @@ -2304,6 +2349,17 @@ BmEnumerateBootOptions ( } Description = BmGetBootDescription (Handles[Index]); + + // + // Skip secondary entries for internal eMMC devices + // + if (StrCmp(Description, L"Internal eMMC") == 0) { + EmmcCount++; + if (EmmcCount > 1) { + continue; + } + } + BootOptions = ReallocatePool ( sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount), sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1), diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c index 6106aa5fc566..e14bdfd00a35 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c @@ -15,7 +15,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define PRODUCT_IDENTIFICATION_LENGTH 16 CONST UINT16 mBmUsbLangId = 0x0409; // English -CHAR16 mBmUefiPrefix[] = L"UEFI "; CHAR16 mBootDescGenericManufacturer[] = L"Generic"; CHAR16 mBootDescSd[] = L"SD Device"; @@ -350,9 +349,8 @@ BmGetDescriptionFromDiskInfo ( SD_CID SdCid; EMMC_CID EmmcCid; CHAR16 *Description; - UINTN Length; + CHAR16 *DescTemp; CONST UINTN ModelNameLength = 40; - CONST UINTN SerialNumberLength = 20; CHAR8 *StrPtr; UINT8 Temp; EFI_DEVICE_PATH_PROTOCOL *DevicePath; @@ -378,26 +376,24 @@ BmGetDescriptionFromDiskInfo ( &BufferSize ); if (!EFI_ERROR (Status)) { - Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16)); + Description = AllocateZeroPool (StrSize (L"SATA: ") + ModelNameLength * sizeof (CHAR16)); ASSERT (Description != NULL); for (Index = 0; Index + 1 < ModelNameLength; Index += 2) { Description[Index] = (CHAR16)IdentifyData.ModelName[Index + 1]; Description[Index + 1] = (CHAR16)IdentifyData.ModelName[Index]; } + Description[Index] = L'\0'; + BmEliminateExtraSpaces (Description); - Length = Index; - Description[Length++] = L' '; - - for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) { - Description[Length + Index] = (CHAR16)IdentifyData.SerialNo[Index + 1]; - Description[Length + Index + 1] = (CHAR16)IdentifyData.SerialNo[Index]; + DescTemp = AllocateZeroPool (0x60); + if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid)) { + StrCatS (DescTemp, 0x60 / sizeof (CHAR16), L"SATA: "); + } else { + StrCatS (DescTemp, 0x60 / sizeof (CHAR16), L"IDE: "); } - - Length += Index; - Description[Length++] = L'\0'; - ASSERT (Length == ModelNameLength + SerialNumberLength + 2); - - BmEliminateExtraSpaces (Description); + StrCatS (DescTemp, 0x60 / sizeof (CHAR16), Description); + StrCpyS(Description, StrSize (DescTemp) / sizeof (CHAR16), DescTemp); + FreePool (DescTemp); } } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid) || CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoUfsInterfaceGuid)) @@ -455,13 +451,7 @@ BmGetDescriptionFromDiskInfo ( return NULL; } - Description = BmGetSdMmcDescription ( - BmGetSdMmcManufacturerName (SdCid.ManufacturerId, FALSE), - SdCid.ProductName, - ARRAY_SIZE (SdCid.ProductName), - SdCid.ProductSerialNumber, - mBootDescSd - ); + Description = L"Internal SD card"; } else if (DevicePathSubType (DevicePath) == MSG_EMMC_DP) { BufferSize = sizeof (EMMC_CID); Status = DiskInfo->Inquiry (DiskInfo, &EmmcCid, &BufferSize); @@ -476,13 +466,7 @@ BmGetDescriptionFromDiskInfo ( Description = BmGetEmmcTypeDescription ((CONTROLLER_DEVICE_PATH *)DevicePath); } - Description = BmGetSdMmcDescription ( - BmGetSdMmcManufacturerName (EmmcCid.ManufacturerId, TRUE), - EmmcCid.ProductName, - ARRAY_SIZE (EmmcCid.ProductName), - EmmcCid.ProductSerialNumber, - Description - ); + Description = L"Internal eMMC"; } else { return NULL; } @@ -510,7 +494,6 @@ BmGetUsbDescription ( CHAR16 NullChar; CHAR16 *Manufacturer; CHAR16 *Product; - CHAR16 *SerialNumber; CHAR16 *Description; EFI_USB_DEVICE_DESCRIPTOR DevDesc; UINTN DescMaxSize; @@ -551,35 +534,22 @@ BmGetUsbDescription ( Product = &NullChar; } - Status = UsbIo->UsbGetStringDescriptor ( - UsbIo, - mBmUsbLangId, - DevDesc.StrSerialNumber, - &SerialNumber - ); - if (EFI_ERROR (Status)) { - SerialNumber = &NullChar; - } - if ((Manufacturer == &NullChar) && - (Product == &NullChar) && - (SerialNumber == &NullChar) - ) + (Product == &NullChar)) { return NULL; } - DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber); + DescMaxSize = StrSize (L"USB: ") + StrSize (Manufacturer) + StrSize (Product); Description = AllocateZeroPool (DescMaxSize); ASSERT (Description != NULL); + StrCatS (Description, DescMaxSize/sizeof (CHAR16), L"USB: "); StrCatS (Description, DescMaxSize/sizeof (CHAR16), Manufacturer); StrCatS (Description, DescMaxSize/sizeof (CHAR16), L" "); StrCatS (Description, DescMaxSize/sizeof (CHAR16), Product); StrCatS (Description, DescMaxSize/sizeof (CHAR16), L" "); - StrCatS (Description, DescMaxSize/sizeof (CHAR16), SerialNumber); - if (Manufacturer != &NullChar) { FreePool (Manufacturer); } @@ -587,11 +557,7 @@ BmGetUsbDescription ( if (Product != &NullChar) { FreePool (Product); } - - if (SerialNumber != &NullChar) { - FreePool (SerialNumber); - } - + BmEliminateExtraSpaces (Description); return Description; @@ -821,6 +787,7 @@ BmGetNvmeDescription ( EFI_NVM_EXPRESS_COMPLETION Completion; NVME_ADMIN_CONTROLLER_DATA ControllerData; CHAR16 *Description; + CHAR16 *DescTemp; CHAR16 *Char; UINTN Index; @@ -889,21 +856,12 @@ BmGetNvmeDescription ( for (Index = 0; Index < ARRAY_SIZE (ControllerData.Mn); Index++) { *(Char++) = (CHAR16)ControllerData.Mn[Index]; } - - *(Char++) = L' '; - for (Index = 0; Index < ARRAY_SIZE (ControllerData.Sn); Index++) { - *(Char++) = (CHAR16)ControllerData.Sn[Index]; - } - - *(Char++) = L' '; - UnicodeValueToStringS ( - Char, - sizeof (CHAR16) * (MAXIMUM_VALUE_CHARACTERS + 1), - 0, - DevicePath.NvmeNamespace->NamespaceId, - 0 - ); BmEliminateExtraSpaces (Description); + DescTemp = AllocateZeroPool (0x60); + StrCatS (DescTemp, 0x60 / sizeof (CHAR16), L"NVMe: "); + StrCatS (DescTemp, 0x60 / sizeof (CHAR16), Description); + StrCpyS(Description, StrSize (DescTemp) / sizeof (CHAR16), DescTemp); + FreePool (DescTemp); } return Description; @@ -1038,7 +996,6 @@ BmGetBootDescription ( BM_BOOT_DESCRIPTION_ENTRY *Entry; CHAR16 *Description; CHAR16 *DefaultDescription; - CHAR16 *Temp; UINTN Index; // @@ -1048,16 +1005,6 @@ BmGetBootDescription ( for (Index = 0; Index < ARRAY_SIZE (mBmBootDescriptionHandlers); Index++) { DefaultDescription = mBmBootDescriptionHandlers[Index](Handle); if (DefaultDescription != NULL) { - // - // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix - // ONLY for core provided boot description handler. - // - Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)); - ASSERT (Temp != NULL); - StrCpyS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), mBmUefiPrefix); - StrCatS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), DefaultDescription); - FreePool (DefaultDescription); - DefaultDescription = Temp; break; } } diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h index a4ff4913d9b6..4bb8955cb54d 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h @@ -46,6 +46,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include +#include #include #include #include diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf index 4007262e46a8..c3b23c94b608 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf +++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf @@ -120,3 +120,4 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMaxRepairCount ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPrioritizeInternal diff --git a/MdeModulePkg/Logo/Logo.c b/MdeModulePkg/Logo/Logo.c index 8ab874d2dadb..73546b32f403 100644 --- a/MdeModulePkg/Logo/Logo.c +++ b/MdeModulePkg/Logo/Logo.c @@ -13,6 +13,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include typedef struct { EFI_IMAGE_ID ImageId; @@ -69,6 +70,10 @@ GetImage ( return EFI_NOT_FOUND; } + if (FixedPcdGetBool (PcdFollowBGRTSpecification)) { + mLogos[Current].Attribute = EdkiiPlatformLogoDisplayAttributeBGRTSpecification; + } + (*Instance)++; *Attribute = mLogos[Current].Attribute; *OffsetX = mLogos[Current].OffsetX; diff --git a/MdeModulePkg/Logo/LogoDxe.inf b/MdeModulePkg/Logo/LogoDxe.inf index 41215d25d853..c5c8ad0bcf39 100644 --- a/MdeModulePkg/Logo/LogoDxe.inf +++ b/MdeModulePkg/Logo/LogoDxe.inf @@ -41,6 +41,7 @@ UefiBootServicesTableLib UefiDriverEntryPoint DebugLib + PcdLib [Protocols] gEfiHiiDatabaseProtocolGuid ## CONSUMES @@ -48,6 +49,9 @@ gEfiHiiPackageListProtocolGuid ## PRODUCES CONSUMES gEdkiiPlatformLogoProtocolGuid ## PRODUCES +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFollowBGRTSpecification ## CONSUMES + [Depex] gEfiHiiDatabaseProtocolGuid AND gEfiHiiImageExProtocolGuid diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 24cc64f6b474..6f52aab2736c 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -1729,16 +1729,20 @@ # @Prompt UFS device initial completion timoeout (us), default value is 600ms. gEfiMdeModulePkgTokenSpaceGuid.PcdUfsInitialCompletionTimeout|600000|UINT32|0x00000036 + ## Inditicates if internal devices will be prioritized over external devices. + # @prompt Prioritize internal devices. + gEfiMdeModulePkgTokenSpaceGuid.PcdPrioritizeInternal|FALSE|BOOLEAN|0x00000043 + [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] ## This PCD defines the Console output row. The default value is 25 according to UEFI spec. # This PCD could be set to 0 then console output would be at max column and max row. # @Prompt Console output row. - gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|25|UINT32|0x40000006 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|40|UINT32|0x40000006 ## This PCD defines the Console output column. The default value is 80 according to UEFI spec. # This PCD could be set to 0 then console output would be at max column and max row. # @Prompt Console output column. - gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|80|UINT32|0x40000007 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|128|UINT32|0x40000007 ## This PCD defines the video horizontal resolution. # If this PCD is set to 0 then video resolution would be at highest resolution. @@ -1767,11 +1771,11 @@ ## Specify the console output column of text setup. # @Prompt Console Output Column of Text Setup - gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn|80|UINT32|0x4000000d + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn|128|UINT32|0x4000000d ## Specify the console output row of text setup. # @Prompt Console Output Row of Text Setup - gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow|25|UINT32|0x4000000e + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow|40|UINT32|0x4000000e ## Specify the Boot Discovery Policy settings # To support configuring from setup page, this PCD should be overridden in DynamicHii type in its platform .dsc: @@ -2284,6 +2288,12 @@ # @Prompt Conduit to use in ArmFfaLib. gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc|TRUE|BOOLEAN|0x10000029 + ## This PCD sets the position of the Boot Logo. + # TRUE - The Logo is positioned according to the BGRT specification. + # FALSE - The logo is positioned in the center of the screen. + # @ Prompt This position of the boot logo + gEfiMdeModulePkgTokenSpaceGuid.PcdFollowBGRTSpecification|FALSE|BOOLEAN|0x10000036 + [PcdsPatchableInModule] ## Specify memory size with page number for PEI code when # Loading Module at Fixed Address feature is enabled. diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni index 7aa83226bba3..90648b5b7a6e 100644 --- a/MdeModulePkg/MdeModulePkg.uni +++ b/MdeModulePkg/MdeModulePkg.uni @@ -1183,6 +1183,10 @@ #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSdMmcGenericTimeoutValue_HELP #language en-US "Indicates the default timeout value for SD/MMC Host Controller operations in microseconds." +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPrioritizeInternal_PROMPT #language en-US "Enable booting from internal devices before external devices." + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPrioritizeInternal_HELP #language en-US "Indicates the if internal devices will be prioritized in boot order." + #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_PROMPT #language en-US "Capsule On Disk relocation device path." #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_HELP #language en-US "Full device path of platform specific device to store Capsule On Disk temp relocation file.
" @@ -1358,3 +1362,9 @@ #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarSupport_HELP #language en-US "Indicates if the PCIe Resizable BAR Capability Supported.

\n" "TRUE - PCIe Resizable BAR Capability is supported.
\n" "FALSE - PCIe Resizable BAR Capability is not supported.
" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFollowBGRTSpecification_PROMPT #language en-US "The position of the Boot Logo" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFollowBGRTSpecification_HELP #language en-US "Sets the position of the Logo. When set to true, the Logo is positioned according to the" + " BGRT specification, 38.2% from the top of the screen." + diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h index a7b15a8a455c..8c75e3c94510 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h @@ -85,8 +85,8 @@ extern BOOLEAN gMisMatch; // // Display definitions // -#define LEFT_ONEOF_DELIMITER L'<' -#define RIGHT_ONEOF_DELIMITER L'>' +#define LEFT_ONEOF_DELIMITER L'[' +#define RIGHT_ONEOF_DELIMITER L']' #define LEFT_NUMERIC_DELIMITER L'[' #define RIGHT_NUMERIC_DELIMITER L']' @@ -94,8 +94,8 @@ extern BOOLEAN gMisMatch; #define LEFT_CHECKBOX_DELIMITER L'[' #define RIGHT_CHECKBOX_DELIMITER L']' -#define CHECK_ON L'X' -#define CHECK_OFF L' ' +#define CHECK_ON L"Enabled" +#define CHECK_OFF L"Disabled" #define TIME_SEPARATOR L':' #define DATE_SEPARATOR L'/' diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c index 0d4cfa4cf06f..d36601c86133 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c @@ -1363,16 +1363,14 @@ ProcessOptions ( } else { *OptionString = AllocateZeroPool (BufferSize); ASSERT (*OptionString); - - *OptionString[0] = LEFT_CHECKBOX_DELIMITER; - - if (QuestionValue->Value.b) { - *(OptionString[0] + 1) = CHECK_ON; - } else { - *(OptionString[0] + 1) = CHECK_OFF; - } - - *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER; + CHAR16 *CheckString = (QuestionValue->Value.b) ? CHECK_ON : CHECK_OFF; + CHAR16 Delimiter[2]; + Delimiter[1] = L'\0'; + Delimiter[0] = LEFT_CHECKBOX_DELIMITER; + NewStrCat (OptionString[0], BufferSize, Delimiter); + NewStrCat (OptionString[0], BufferSize, CheckString); + Delimiter[0] = RIGHT_CHECKBOX_DELIMITER; + NewStrCat (OptionString[0], BufferSize, Delimiter); } break; diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c index 5c168c8751dc..e7338b267b2d 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c @@ -1136,19 +1136,7 @@ FindFvbForFtw ( FtwDevice->WorkBlockSize = BlockSize; FtwDevice->FtwWorkSpaceBase = (UINTN)(FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FtwDevice->WorkBlockSize * (LbaIndex - 1))); FtwDevice->NumberOfWorkSpaceBlock = FTW_BLOCKS (FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize, FtwDevice->WorkBlockSize); - if (FtwDevice->FtwWorkSpaceSize >= FtwDevice->WorkBlockSize) { - // - // Check the alignment of work space address and length, they should be block size aligned when work space size is larger than one block size. - // - if (((FtwDevice->WorkSpaceAddress & (FtwDevice->WorkBlockSize - 1)) != 0) || - ((FtwDevice->WorkSpaceLength & (FtwDevice->WorkBlockSize - 1)) != 0)) - { - DEBUG ((DEBUG_ERROR, "Ftw: Work space address or length is not block size aligned when work space size is larger than one block size\n")); - FreePool (HandleBuffer); - ASSERT (FALSE); - return EFI_ABORTED; - } - } else if ((FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize) > FtwDevice->WorkBlockSize) { + if ((FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize) > FtwDevice->WorkBlockSize) { DEBUG ((DEBUG_ERROR, "Ftw: The work space range should not span blocks when work space size is less than one block size\n")); FreePool (HandleBuffer); ASSERT (FALSE); @@ -1186,23 +1174,6 @@ FindFvbForFtw ( ASSERT (FALSE); return EFI_ABORTED; } - - // - // Check the alignment of spare area address and length, they should be block size aligned - // - if (((FtwDevice->SpareAreaAddress & (FtwDevice->SpareBlockSize - 1)) != 0) || - ((FtwDevice->SpareAreaLength & (FtwDevice->SpareBlockSize - 1)) != 0)) - { - DEBUG ((DEBUG_ERROR, "Ftw: Spare area address or length is not block size aligned\n")); - FreePool (HandleBuffer); - // - // Report Status Code EFI_SW_EC_ABORTED. - // - REPORT_STATUS_CODE ((EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ABORTED)); - ASSERT (FALSE); - CpuDeadLoop (); - } - break; } } diff --git a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc index ff5346aae7a4..383edf4efe49 100644 --- a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc +++ b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc @@ -9,6 +9,7 @@ !endif Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf + Tcg2PhysicalPresencePlatformLib|OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf !else Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf diff --git a/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h new file mode 100644 index 000000000000..76bfd2a87fa0 --- /dev/null +++ b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h @@ -0,0 +1,29 @@ +/** @file + Returns the platform specific Physical Presence configuration. + + Copyright (C) 2020 9elements GmbH + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__ +#define __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__ + +#include + +/** + Reads the platform specific Physical Presence configuration. + + @param[out] The Config structure to read to. + @param[out] The PPIinMMIO is True when the PPI is in MMIO memory space + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. +**/ +EFI_STATUS +TpmPPIPlatformReadConfig ( + OUT QEMU_FWCFG_TPM_CONFIG *Config, + OUT BOOLEAN *PPIinMMIO + ); + +#endif diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c index 403802025156..cc9bd9f00d45 100644 --- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c +++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c @@ -27,8 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include -#include #include +#include #include #include #include @@ -40,42 +40,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent EFI_HII_HANDLE mTcg2PpStringPackHandle; +/* Wait 3 minutes for user input */ +#define TIMEOUT (1000 * 1000 * 60 * 3) + #define TPM_PPI_FLAGS (QEMU_TPM_PPI_FUNC_ALLOWED_USR_REQ) STATIC volatile QEMU_TPM_PPI *mPpi; -/** - Reads QEMU PPI config from fw_cfg. - - @param[out] The Config structure to read to. - - @retval EFI_SUCCESS Operation completed successfully. - @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. -**/ -STATIC -EFI_STATUS -QemuTpmReadConfig ( - OUT QEMU_FWCFG_TPM_CONFIG *Config - ) -{ - EFI_STATUS Status; - FIRMWARE_CONFIG_ITEM FwCfgItem; - UINTN FwCfgSize; - - Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize); - if (EFI_ERROR (Status)) { - return Status; - } - - if (FwCfgSize != sizeof (*Config)) { - return EFI_PROTOCOL_ERROR; - } - - QemuFwCfgSelectItem (FwCfgItem); - QemuFwCfgReadBytes (sizeof (*Config), Config); - return EFI_SUCCESS; -} - /** Initializes QEMU PPI memory region. @@ -90,6 +61,7 @@ QemuTpmInitPPI ( { EFI_STATUS Status; QEMU_FWCFG_TPM_CONFIG Config; + BOOLEAN PPIinMMIO; EFI_PHYSICAL_ADDRESS PpiAddress64; EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; UINTN Idx; @@ -98,7 +70,7 @@ QemuTpmInitPPI ( return EFI_SUCCESS; } - Status = QemuTpmReadConfig (&Config); + Status = TpmPPIPlatformReadConfig (&Config, &PPIinMMIO); if (EFI_ERROR (Status)) { return Status; } @@ -124,12 +96,20 @@ QemuTpmInitPPI ( goto InvalidPpiAddress; } - if (!EFI_ERROR (Status) && - ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) && - (Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent))) - { - DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); - goto InvalidPpiAddress; + if (PPIinMMIO) { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent)) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } + } else { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } } for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) { @@ -359,12 +339,16 @@ Tcg2ExecutePhysicalPresence ( STATIC BOOLEAN Tcg2ReadUserKey ( - IN BOOLEAN CautionKey + IN BOOLEAN CautionKey, + IN UINTN Timeout ) { EFI_STATUS Status; EFI_INPUT_KEY Key; UINT16 InputKey; + UINTN Delay; + + Delay = Timeout / 50; InputKey = 0; do { @@ -383,7 +367,13 @@ Tcg2ReadUserKey ( InputKey = Key.ScanCode; } } - } while (InputKey == 0); + gBS->Stall (50); + Delay--; + } while (InputKey == 0 && Delay > 0); + + if (Delay == 0) { + return FALSE; + } if (InputKey != SCAN_ESC) { return TRUE; @@ -652,7 +642,7 @@ Tcg2UserConfirm ( FreePool (ConfirmText); HiiRemovePackages (mTcg2PpStringPackHandle); - if (Tcg2ReadUserKey (CautionKey)) { + if (Tcg2ReadUserKey (CautionKey, TIMEOUT)) { return TRUE; } diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf index 5b5417c32150..ababaec9e01e 100644 --- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf +++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf @@ -57,12 +57,12 @@ HobLib MemoryAllocationLib PrintLib - QemuFwCfgLib Tpm2CommandLib UefiBootManagerLib UefiBootServicesTableLib UefiLib UefiRuntimeServicesTableLib + Tcg2PhysicalPresencePlatformLib [Protocols] gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c new file mode 100644 index 000000000000..baef59d2efba --- /dev/null +++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c @@ -0,0 +1,56 @@ +/** @file + Returns the platform specific configuration for the QEMU PPI. + + Caution: This module requires additional review when modified. + This driver will have external input - variable. + This external input must be validated carefully to avoid security issue. + +Copyright (C) 2018, Red Hat, Inc. +Copyright (c) 2018, IBM Corporation. All rights reserved.
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include + +/** + Reads QEMU PPI config from fw_cfg. + + @param[out] The Config structure to read to. + @param[out] The PPIinMMIO is True when the PPI is in MMIO memory space + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. +**/ +EFI_STATUS +TpmPPIPlatformReadConfig ( + OUT QEMU_FWCFG_TPM_CONFIG *Config, + OUT BOOLEAN *PPIinMMIO + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + + Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (FwCfgSize != sizeof (*Config)) { + return EFI_PROTOCOL_ERROR; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (sizeof (*Config), Config); + + *PPIinMMIO = TRUE; + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf new file mode 100644 index 000000000000..0ea0c08d4c55 --- /dev/null +++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf @@ -0,0 +1,36 @@ +## @file +# Returns the platform specific configuration for the QEMU PPI. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (C) 2018, Red Hat, Inc. +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2PhysicalPresencePlatformLibQemu + FILE_GUID = 9336E7F0-6CA1-4E6D-A0E9-DFE5F077AA02 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresencePlatformLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeTcg2PhysicalPresencePlatformLib.c + +[Packages] + OvmfPkg/OvmfPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + QemuFwCfgLib diff --git a/SecurityPkg/Include/Library/TcgPhysicalPresenceLib.h b/SecurityPkg/Include/Library/TcgPhysicalPresenceLib.h index db9645b15df6..120911eeaf52 100644 --- a/SecurityPkg/Include/Library/TcgPhysicalPresenceLib.h +++ b/SecurityPkg/Include/Library/TcgPhysicalPresenceLib.h @@ -22,8 +22,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent to display request information and get user input to confirm the request. This API should also be invoked as early as possible as TPM is locked in this function. + @retval EFI_SUCCESS Flags were returns successfully. + @retval other Failed to process. + **/ -VOID +EFI_STATUS EFIAPI TcgPhysicalPresenceLibProcessRequest ( VOID @@ -45,4 +48,25 @@ TcgPhysicalPresenceLibNeedUserConfirm ( VOID ); +/** + The handler for TPM physical presence function: + Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. + + This API should be invoked in OS runtime phase to interface with ACPI method. + + Caution: This function may receive untrusted input. + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] RequestParameter TPM physical presence operation request parameter. + + @return Return Code for Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. +**/ +UINT32 +EFIAPI +TcgPhysicalPresenceLibSubmitRequestToPreOSFunction ( + IN UINT32 OperationRequest, + IN UINT32 RequestParameter + ); #endif diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni index ee7fa081b6c6..08a7fe2be870 100644 --- a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni @@ -8,8 +8,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #langdef en-US "English" -#string STR_TCG2_TITLE #language en-US "TCG2 Configuration" -#string STR_TCG2_HELP #language en-US "Press to select TCG2 Setup options." +#string STR_TCG2_TITLE #language en-US "TPM 2.0 Configuration" +#string STR_TCG2_HELP #language en-US "Press to select TPM Setup options." #string STR_TCG2_DEVICE_STATE_PROMPT #language en-US "Current TPM Device" #string STR_TCG2_DEVICE_STATE_HELP #language en-US "Current TPM Device: Disable, TPM1.2, or TPM2.0" diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c index 85a852842d50..febf54bffe21 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c @@ -2852,6 +2852,15 @@ DriverEntry ( DEBUG ((DEBUG_INFO, "Tcg2.NumberOfPCRBanks - 0x%08x\n", mTcgDxeData.BsCap.NumberOfPCRBanks)); DEBUG ((DEBUG_INFO, "Tcg2.ActivePcrBanks - 0x%08x\n", mTcgDxeData.BsCap.ActivePcrBanks)); + // HACK: This is usually done in Tcg2Pei + UINT32 Tpm2PcrMask; + Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask); + if (Tpm2PcrMask != mTcgDxeData.BsCap.HashAlgorithmBitmap) { + Tpm2PcrMask &= mTcgDxeData.BsCap.HashAlgorithmBitmap; + Status = PcdSet32S (PcdTpm2HashMask, Tpm2PcrMask); + ASSERT_EFI_ERROR (Status); + } + if (mTcgDxeData.BsCap.TPMPresentFlag) { // // Setup the log area and copy event log from hob list to it diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf index a645474bf3cd..744ab0f2d4ff 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf @@ -108,7 +108,8 @@ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml ## PRODUCES gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa ## PRODUCES gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication ## CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask ## PRODUCES [Depex] # According to PcdTpm2AcpiTableRev definition in SecurityPkg.dec diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf index 24428e050c3f..ee43dc429bf7 100644 --- a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf +++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf @@ -48,6 +48,7 @@ PcdLib PrintLib Tpm12DeviceLib + TcgPhysicalPresenceLib [Guids] ## SOMETIMES_PRODUCES ## Variable:L"PhysicalPresence" diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c index 52ea1ac3aeaf..2570b9cac197 100644 --- a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c +++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c @@ -7,6 +7,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "TcgConfigImpl.h" +#include +#include CHAR16 mTcgStorageName[] = L"TCG_CONFIGURATION"; @@ -41,6 +43,8 @@ HII_VENDOR_DEVICE_PATH mTcgHiiVendorDevicePath = { } }; +UINT8 mCurrentPpRequest; + /** Get current state of TPM device. @@ -302,6 +306,7 @@ SavePpRequest ( EFI_STATUS Status; UINTN DataSize; EFI_PHYSICAL_PRESENCE PpData; + UINT32 ReturnCode; // // Save TPM command to variable. @@ -330,7 +335,19 @@ SavePpRequest ( return Status; } - return EFI_SUCCESS; + ReturnCode = TcgPhysicalPresenceLibSubmitRequestToPreOSFunction (PpRequest, 0); + if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) { + mCurrentPpRequest = PpRequest; + Status = EFI_SUCCESS; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE) { + Status = EFI_OUT_OF_RESOURCES; + } else if (ReturnCode == TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_DEVICE_ERROR; + } + + return Status; } /** diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.uni b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.uni index b5bb899825ff..8dd4961bd4b4 100644 --- a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.uni +++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigStrings.uni @@ -8,8 +8,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #langdef en-US "English" -#string STR_TPM_TITLE #language en-US "TCG Configuration" -#string STR_TPM_HELP #language en-US "Press to select TCG Setup options." +#string STR_TPM_TITLE #language en-US "TPM 1.2 Configuration" +#string STR_TPM_HELP #language en-US "Press to select TPM Setup options." #string STR_TPM_STATE_PROMPT #language en-US "Current TPM State" #string STR_TPM_STATE_HELP #language en-US "Current TPM device state: enabled or disabled; activated or deactivated." #string STR_TPM_STATE_CONTENT #language en-US "" diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c index ae3e94368bd9..4e0b2d1d9b79 100644 --- a/ShellPkg/Application/Shell/Shell.c +++ b/ShellPkg/Application/Shell/Shell.c @@ -548,14 +548,6 @@ UefiMain ( ); } - // - // Display the mapping - // - if ((PcdGet8 (PcdShellSupportLevel) >= 2) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) { - Status = RunCommand (L"map"); - ASSERT_EFI_ERROR (Status); - } - // // init all the built in alias' // @@ -619,12 +611,10 @@ UefiMain ( ConInHandle = NULL; } - if (!EFI_ERROR (Status) && (PcdGet8 (PcdShellSupportLevel) >= 1)) { - // - // process the startup script or launch the called app. - // - Status = DoStartupScript (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath); - } + // + // show welcome notice + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_WELCOME), ShellInfoObject.HiiHandle); if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit () && ((PcdGet8 (PcdShellSupportLevel) >= 3) || PcdGetBool (PcdShellForceConsole)) && !EFI_ERROR (Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { // diff --git a/ShellPkg/Application/Shell/Shell.uni b/ShellPkg/Application/Shell/Shell.uni index 7dd0072601d0..ff16c401c392 100644 --- a/ShellPkg/Application/Shell/Shell.uni +++ b/ShellPkg/Application/Shell/Shell.uni @@ -50,3 +50,4 @@ #string STR_SHELL_IMAGE_NOT_APP #language en-US "The image is not an application.\r\n" +#string STR_SHELL_WELCOME #language en-US "\r\nWelcome to the UEFI Shell!\r\n\r\nIf you wound up here by mistake, just type 'exit' to return to the UEFI Options Menu.\r\n\r\n" diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.c b/UefiCpuPkg/CpuDxe/CpuDxe.c index 472de55180e1..bf039787101c 100644 --- a/UefiCpuPkg/CpuDxe/CpuDxe.c +++ b/UefiCpuPkg/CpuDxe/CpuDxe.c @@ -1033,11 +1033,6 @@ InitializeCpu ( ); ASSERT_EFI_ERROR (Status); - // - // Install EFI memory attribute Protocol - // - InstallEfiMemoryAttributeProtocol (mCpuHandle); - // // Refresh GCD memory space map according to MTRR value. // diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf index b2954ba23446..fca74c44b334 100644 --- a/UefiCpuPkg/CpuDxe/CpuDxe.inf +++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf @@ -75,7 +75,6 @@ [Protocols] gEfiCpuArchProtocolGuid ## PRODUCES - gEfiMemoryAttributeProtocolGuid ## PRODUCES gEfiMpServiceProtocolGuid ## PRODUCES gEfiSmmBase2ProtocolGuid ## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/CpuPageTable.c index 9a519bcb7ec0..c5bf2285ac1a 100644 --- a/UefiCpuPkg/CpuDxe/CpuPageTable.c +++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c @@ -1436,298 +1436,3 @@ InitializePageTableLib ( return; } - -/** - This function set given attributes of the memory region specified by - BaseAddress and Length. - The valid Attributes is EFI_MEMORY_RP, EFI_MEMORY_XP, and EFI_MEMORY_RO. - - @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance. - @param BaseAddress The physical address that is the start address of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memory - region. - - @retval EFI_SUCCESS The attributes were set for the memory region. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combination of - attributes that cannot be set together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specified - by BaseAddress and Length. - The bit mask of attributes is not supported for - the memory resource range specified by - BaseAddress and Length. - @retval EFI_OUT_OF_RESOURCES Requested attributes cannot be applied due to lack of - system resources. - @retval EFI_ACCESS_DENIED Attributes for the requested memory region are - controlled by system firmware and cannot be updated - via the protocol. -**/ -EFI_STATUS -EFIAPI -EfiSetMemoryAttributes ( - IN EFI_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ) -{ - RETURN_STATUS Status; - BOOLEAN IsModified; - BOOLEAN IsSplitted; - - DEBUG ((DEBUG_VERBOSE, "%a: 0x%lx - 0x%lx (0x%lx)\n", __func__, BaseAddress, Length, Attributes)); - - if (Attributes == 0) { - DEBUG ((DEBUG_ERROR, "%a: Error - Attributes == 0\n", __func__)); - return EFI_INVALID_PARAMETER; - } - - if ((Attributes & ~EFI_MEMORY_ACCESS_MASK) != 0) { - DEBUG ((DEBUG_ERROR, "%a: Error - Attributes(0x%lx) invalid\n", __func__, Attributes)); - return EFI_INVALID_PARAMETER; - } - - if (Length == 0) { - DEBUG ((DEBUG_ERROR, "%a: Length is 0!\n", __func__)); - return RETURN_INVALID_PARAMETER; - } - - Status = ConvertMemoryPageAttributes (NULL, BaseAddress, Length, Attributes, PageActionSet, NULL, &IsSplitted, &IsModified); - if (!EFI_ERROR (Status)) { - if (IsModified) { - // - // Flush TLB as last step. - // - // Note: Since APs will always init CR3 register in HLT loop mode or do - // TLB flush in MWAIT loop mode, there's no need to flush TLB for them - // here. - // - CpuFlushTlb (); - } - } else { - DEBUG ((DEBUG_ERROR, "%a: Failed in ConvertMemoryPageAttributes (%r)\n", __func__, Status)); - } - - return Status; -} - -/** - This function clears given attributes of the memory region specified by - BaseAddress and Length. - The valid Attributes is EFI_MEMORY_RP, EFI_MEMORY_XP, and EFI_MEMORY_RO. - @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance. - @param BaseAddress The physical address that is the start address of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to clear for the memory - region. - - @retval EFI_SUCCESS The attributes were cleared for the memory region. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combination of - attributes that cannot be cleared together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specified - by BaseAddress and Length. - The bit mask of attributes is not supported for - the memory resource range specified by - BaseAddress and Length. - @retval EFI_OUT_OF_RESOURCES Requested attributes cannot be applied due to lack of - system resources. - @retval EFI_ACCESS_DENIED Attributes for the requested memory region are - controlled by system firmware and cannot be updated - via the protocol. -**/ -EFI_STATUS -EFIAPI -EfiClearMemoryAttributes ( - IN EFI_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ) -{ - RETURN_STATUS Status; - BOOLEAN IsModified; - BOOLEAN IsSplitted; - - DEBUG ((DEBUG_VERBOSE, "%a: 0x%lx - 0x%lx (0x%lx)\n", __func__, BaseAddress, Length, Attributes)); - - if (Attributes == 0) { - DEBUG ((DEBUG_ERROR, "%a: Error - Attributes == 0\n", __func__)); - return EFI_INVALID_PARAMETER; - } - - if ((Attributes & ~EFI_MEMORY_ACCESS_MASK) != 0) { - DEBUG ((DEBUG_ERROR, "%a: Error - Attributes(0x%lx) invalid\n", __func__, Attributes)); - return EFI_INVALID_PARAMETER; - } - - if (Length == 0) { - DEBUG ((DEBUG_ERROR, "%a: Length is 0!\n", __func__)); - return RETURN_INVALID_PARAMETER; - } - - Status = ConvertMemoryPageAttributes (NULL, BaseAddress, Length, Attributes, PageActionClear, NULL, &IsSplitted, &IsModified); - if (!EFI_ERROR (Status)) { - if (IsModified) { - // - // Flush TLB as last step. - // - // Note: Since APs will always init CR3 register in HLT loop mode or do - // TLB flush in MWAIT loop mode, there's no need to flush TLB for them - // here. - // - CpuFlushTlb (); - } - } else { - DEBUG ((DEBUG_ERROR, "%a: Failed in ConvertMemoryPageAttributes (%r)\n", __func__, Status)); - } - - return Status; -} - -/** - This function retrieves the attributes of the memory region specified by - BaseAddress and Length. If different attributes are got from different part - of the memory region, EFI_NO_MAPPING will be returned. - - @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance. - @param BaseAddress The physical address that is the start address of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes Pointer to attributes returned. - - @retval EFI_SUCCESS The attributes got for the memory region. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes is NULL. - @retval EFI_NO_MAPPING Attributes are not consistent cross the memory - region. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specified - by BaseAddress and Length. -**/ -EFI_STATUS -EFIAPI -EfiGetMemoryAttributes ( - IN EFI_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - OUT UINT64 *Attributes - ) -{ - PAGE_TABLE_LIB_PAGING_CONTEXT CurrentPagingContext; - EFI_PHYSICAL_ADDRESS Address; - UINT64 *PageEntry; - UINT64 MemAttr; - PAGE_ATTRIBUTE PageAttr; - INT64 Size; - UINT64 AddressEncMask; - - DEBUG ((DEBUG_VERBOSE, "%a: 0x%lx - 0x%lx\n", __func__, BaseAddress, Length)); - - if (!IS_ALIGNED (BaseAddress, EFI_PAGE_SIZE)) { - DEBUG ((DEBUG_ERROR, "%a: BaseAddress(0x%lx) is not aligned!\n", __func__, BaseAddress)); - return EFI_UNSUPPORTED; - } - - if (!IS_ALIGNED (Length, EFI_PAGE_SIZE)) { - DEBUG ((DEBUG_ERROR, "%a: Length(0x%lx) is not aligned!\n", __func__, Length)); - return EFI_UNSUPPORTED; - } - - if (Length == 0) { - DEBUG ((DEBUG_ERROR, "%a: Length is 0!\n", __func__)); - return RETURN_INVALID_PARAMETER; - } - - if (Attributes == NULL) { - DEBUG ((DEBUG_ERROR, "%a: Attributes is NULL\n", __func__)); - return EFI_INVALID_PARAMETER; - } - - Size = (INT64)Length; - MemAttr = (UINT64)-1; - - // Make sure AddressEncMask is contained to smallest supported address field. - // - AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64; - - GetCurrentPagingContext (&CurrentPagingContext); - - do { - PageEntry = GetPageTableEntry (&CurrentPagingContext, BaseAddress, &PageAttr); - if ((PageEntry == NULL) || (PageAttr == PageNone)) { - return EFI_UNSUPPORTED; - } - - // - // If the memory range is cross page table boundary, make sure they - // share the same attribute. Return EFI_NO_MAPPING if not. - // - *Attributes = GetAttributesFromPageEntry (PageEntry); - if ((MemAttr != (UINT64)-1) && (*Attributes != MemAttr)) { - return EFI_NO_MAPPING; - } - - switch (PageAttr) { - case Page4K: - Address = *PageEntry & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64; - Size -= (EFI_PAGE_SIZE - (BaseAddress - Address)); - BaseAddress += (EFI_PAGE_SIZE - (BaseAddress - Address)); - break; - - case Page2M: - Address = *PageEntry & ~AddressEncMask & PAGING_2M_ADDRESS_MASK_64; - Size -= SIZE_2MB - (BaseAddress - Address); - BaseAddress += SIZE_2MB - (BaseAddress - Address); - break; - - case Page1G: - Address = *PageEntry & ~AddressEncMask & PAGING_1G_ADDRESS_MASK_64; - Size -= SIZE_1GB - (BaseAddress - Address); - BaseAddress += SIZE_1GB - (BaseAddress - Address); - break; - - default: - return EFI_UNSUPPORTED; - } - - MemAttr = *Attributes; - } while (Size > 0); - - DEBUG ((DEBUG_VERBOSE, "%a: Attributes is 0x%lx\n", __func__, *Attributes)); - - return EFI_SUCCESS; -} - -EFI_MEMORY_ATTRIBUTE_PROTOCOL mMemoryAttributeProtocol = { - EfiGetMemoryAttributes, - EfiSetMemoryAttributes, - EfiClearMemoryAttributes, -}; - -/** - Install Efi Memory Attribute Protocol. - - @param Handle A pointer to the EFI_HANDLE on which the interface is to be installed - -**/ -VOID -InstallEfiMemoryAttributeProtocol ( - IN EFI_HANDLE Handle - ) -{ - EFI_STATUS Status; - - Status = gBS->InstallMultipleProtocolInterfaces ( - &Handle, - &gEfiMemoryAttributeProtocolGuid, - &mMemoryAttributeProtocol, - NULL - ); - ASSERT_EFI_ERROR (Status); -} diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.h b/UefiCpuPkg/CpuDxe/CpuPageTable.h index f2694452f54a..607e936b8ac7 100644 --- a/UefiCpuPkg/CpuDxe/CpuPageTable.h +++ b/UefiCpuPkg/CpuDxe/CpuPageTable.h @@ -10,7 +10,6 @@ #define _PAGE_TABLE_LIB_H_ #include -#include #define PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE BIT0 #define PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE BIT1 @@ -154,15 +153,4 @@ GetPagingDetails ( OUT UINT32 **Attributes OPTIONAL ); -/** - Install Efi Memory Attribute Protocol. - - @param Handle A pointer to the EFI_HANDLE on which the interface is to be installed - -**/ -VOID -InstallEfiMemoryAttributeProtocol ( - IN EFI_HANDLE Handle - ); - #endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm index 3d64ac908010..ed79514603a1 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm @@ -57,7 +57,7 @@ ALIGN 8 AsmIdtVectorBegin: %assign Vector 0 %rep 256 - push strict dword %[Vector] ; This instruction pushes sign-extended 8-byte value on stack + push strict qword %[Vector] ; This instruction pushes sign-extended 8-byte value on stack push rax %ifdef NO_ABSOLUTE_RELOCS_IN_TEXT mov rax, strict qword 0 ; mov rax, ASM_PFX(CommonInterruptEntry) @@ -70,7 +70,7 @@ AsmIdtVectorBegin: AsmIdtVectorEnd: HookAfterStubHeaderBegin: - push strict dword 0 ; 0 will be fixed + push strict qword 0 ; 0 will be fixed VectorNum: push rax %ifdef NO_ABSOLUTE_RELOCS_IN_TEXT @@ -490,3 +490,4 @@ ASM_PFX(AsmVectorNumFixup): mov [rcx + (VectorNum - 4 - HookAfterStubHeaderBegin)], al ret + diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm index 95ee65e28828..b3c2b954f1a6 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm @@ -318,7 +318,6 @@ MwaitCheckGeneric: MwaitLoopGeneric: cli mov rax, rsp ; Set Monitor Address - sub eax, 8 ; To ensure the monitor address is in the page table xor ecx, ecx ; ecx = 0 xor edx, edx ; edx = 0 monitor diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c index bfe02f3cb981..80d6efd09d4c 100644 --- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c +++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c @@ -161,6 +161,10 @@ MtrrLibIsMtrrSupported ( CPUID_VERSION_INFO_EDX Edx; MSR_IA32_MTRRCAP_REGISTER MtrrCap; + if (PcdGetBool(PcdCpuDisableMtrrProgramming)) { + return FALSE; + } + // // MTRR is not supported in TD-Guest. // diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf b/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf index 4c9ea2def3bd..611fdc704722 100644 --- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf +++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf @@ -37,4 +37,4 @@ [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs ## SOMETIMES_CONSUMES - + gUefiCpuPkgTokenSpaceGuid.PcdCpuDisableMtrrProgramming ## CONSUMES diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index 3789ee95351c..79a881078adb 100644 --- a/UefiCpuPkg/UefiCpuPkg.dec +++ b/UefiCpuPkg/UefiCpuPkg.dec @@ -325,6 +325,10 @@ # @Prompt SMM Code Access Check. gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable|TRUE|BOOLEAN|0x60000013 + ## Disables MTRR programming in case it's already programmed by FSB. + # @Prompt Disable MTRR programming. + gUefiCpuPkgTokenSpaceGuid.PcdCpuDisableMtrrProgramming|FALSE|BOOLEAN|0x00000017 + ## Specifies the number of variable MTRRs reserved for OS use. The default number of # MTRRs reserved for OS use is 2. # @Prompt Number of reserved variable MTRRs. diff --git a/UefiCpuPkg/UefiCpuPkg.uni b/UefiCpuPkg/UefiCpuPkg.uni index 25a7176194f1..81f9525860c1 100644 --- a/UefiCpuPkg/UefiCpuPkg.uni +++ b/UefiCpuPkg/UefiCpuPkg.uni @@ -156,9 +156,13 @@ #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuHotPlugDataAddress_HELP #language en-US "Contains the pointer to a CPU Hot Plug Data structure if CPU hot-plug is supported." -#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuNumberOfReservedVariableMtrrs_PROMPT #language en-US "Number of reserved variable MTRRs" +#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuDisableMtrrProgramming_PROMPT #language en-US "Number of reserved variable MTRRs" -#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuNumberOfReservedVariableMtrrs_HELP #language en-US "Specifies the number of variable MTRRs reserved for OS use." +#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuDisableMtrrProgramming_HELP #language en-US "Specifies the number of variable MTRRs reserved for OS use." + +#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuNumberOfReservedVariableMtrrs_PROMPT #language en-US "Disable MTRR programming." + +#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuNumberOfReservedVariableMtrrs_HELP #language en-US "Disables MTRR programming in case it's already programmed by FSB." #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuApLoopMode_PROMPT #language en-US "The AP wait loop state" diff --git a/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c b/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c index 215bc60f7794..0cebb83e8230 100644 --- a/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c +++ b/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c @@ -7,6 +7,7 @@ **/ #include "BlSupportDxe.h" +#include /** Main entry for the bootloader support DXE module. @@ -29,6 +30,7 @@ BlDxeEntryPoint ( EFI_HOB_GUID_TYPE *GuidHob; EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo; ACPI_BOARD_INFO *AcpiBoardInfo; + UINTN Size; // // Find the frame buffer information and update PCDs @@ -56,6 +58,27 @@ BlDxeEntryPoint ( ASSERT_EFI_ERROR (Status); Status = PcdSet64S (PcdPciExpressBaseSize, AcpiBoardInfo->PcieBaseSize); ASSERT_EFI_ERROR (Status); + + if (AcpiBoardInfo->TPM12Present) + { + Size = sizeof (gEfiTpmDeviceInstanceTpm12Guid); + Status = PcdSetPtrS ( + PcdTpmInstanceGuid, + &Size, + &gEfiTpmDeviceInstanceTpm12Guid + ); + ASSERT_EFI_ERROR (Status); + } + else if (AcpiBoardInfo->TPM20Present) + { + Size = sizeof (gEfiTpmDeviceInstanceTpm20DtpmGuid); + Status = PcdSetPtrS ( + PcdTpmInstanceGuid, + &Size, + &gEfiTpmDeviceInstanceTpm20DtpmGuid + ); + ASSERT_EFI_ERROR (Status); + } } Status = BlArchAdditionalOps (ImageHandle, SystemTable); diff --git a/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf b/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf index 401b99f9b6e0..9dc98dfb959a 100644 --- a/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf +++ b/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf @@ -38,6 +38,7 @@ MdeModulePkg/MdeModulePkg.dec UefiPayloadPkg/UefiPayloadPkg.dec UefiCpuPkg/UefiCpuPkg.dec + SecurityPkg/SecurityPkg.dec [LibraryClasses] UefiDriverEntryPoint @@ -52,6 +53,8 @@ [Guids] gUefiAcpiBoardInfoGuid gEfiGraphicsInfoHobGuid + gEfiTpmDeviceInstanceTpm20DtpmGuid ## SOMETIMES_CONSUMES + gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_CONSUMES [Protocols] gEfiCpuArchProtocolGuid @@ -63,6 +66,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## SOMETIMES_PRODUCES [Pcd.AARCH64] gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/ComponentName.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/ComponentName.c new file mode 100644 index 000000000000..f1241abb52a7 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/ComponentName.c @@ -0,0 +1,235 @@ +/** @file + UEFI Component Name(2) protocol implementation for SD/MMC host controller driver. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciCbComponentName = { + SdMmcPciCbComponentNameGetDriverName, + SdMmcPciCbComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSdMmcPciCbComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)SdMmcPciCbComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)SdMmcPciCbComponentNameGetControllerName, + "en" +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdMmcPciCbDriverNameTable[] = { + { "eng;en", L"Edkii Sd/Mmc Host Controller Driver" }, + { NULL, NULL } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdMmcPciCbControllerNameTable[] = { + { "eng;en", L"Edkii Sd/Mmc Host Controller" }, + { NULL, NULL } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdMmcPciCbChildNameTable[] = { + { "eng;en", L"eMMC Storage Device" }, + { NULL, NULL } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +SdMmcPciCbComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mSdMmcPciCbDriverNameTable, + DriverName, + (BOOLEAN)(This == &gSdMmcPciCbComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +SdMmcPciCbComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + + if ((Language == NULL) || (ControllerName == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // If ChildHandle is NULL, return the controller (PCI device) name + // If ChildHandle is not NULL, return the child device (eMMC) name + // + if (ChildHandle == NULL) { + // + // Make sure this driver is currently managing ControllerHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gSdMmcPciCbDriverBinding.DriverBindingHandle, + &gEfiPciIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mSdMmcPciCbControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gSdMmcPciCbComponentName) + ); + } else { + // + // Return child device name (eMMC) + // + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiBlockIoProtocolGuid, + (VOID **)&BlockIo, + gSdMmcPciCbDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // Return child device name from string table + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mSdMmcPciCbChildNameTable, + ControllerName, + (BOOLEAN)(This == &gSdMmcPciCbComponentName) + ); + } +} diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/README.md b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/README.md new file mode 100644 index 000000000000..973e32d4ed6b --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/README.md @@ -0,0 +1,33 @@ +# SdMmcPciCbDxe - Universal Chromebook SDHCI Driver for EDK2 + +**Cb** = Chromebook/Coreboot - Based on Depthcharge's proven SDHCI stack + +## Purpose +Complete port of Depthcharge's SDHCI/MMC driver stack to EDK2. +Uses the proven simple polling approach from Depthcharge that works with GL9763E. + +## Status +🚧 IN PROGRESS - Replacing the problematic generic SdMmcPciHcDxe driver + +## Files +- SdMmcPciDcDxe.inf - Build configuration +- SdMmcPciDcDxe.h - Register definitions (from Depthcharge sdhci.h) +- SdMmcPciDcDxe.c - Driver entry point and PCI binding +- SdMmcPciDcSdhci.c - SDHCI core functions (from Depthcharge sdhci.c) +- SdMmcPciDcMmc.c - MMC/eMMC protocol (from Depthcharge mmc.c) +- SdMmcPciDcGli.c - GL9763E specific code (from Depthcharge sdhci_gli.c) +- SdMmcPciDcBlockIo.c - EDK2 BlockIo protocol implementation + +## Advantages +1. ✅ Proven code - works in Depthcharge +2. ✅ Simple polling - no complex interrupt handling +3. ✅ GL9763E tested - known to work with this exact hardware +4. ✅ Clean slate - no legacy baggage from generic driver + +## Next Steps +1. Complete basic driver structure +2. Port core SDHCI functions +3. Port eMMC initialization +4. Implement BlockIo for EDK2 +5. Test and iterate + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbBlockIo.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbBlockIo.c new file mode 100644 index 000000000000..1083521a544e --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbBlockIo.c @@ -0,0 +1,389 @@ +/** @file + BlockIo Protocol Implementation + + Copyright (c) 2025, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +/** + Check if media is present and update media status. + For removable media (SD cards), checks PRESENT_STATE register. + For eMMC, always returns TRUE. + + @param[in] Device Device context + + @retval EFI_SUCCESS Media is present + @retval EFI_NO_MEDIA No media in device + @retval EFI_MEDIA_CHANGED Media was changed +**/ +STATIC +EFI_STATUS +CheckMediaPresence ( + IN SD_MMC_CB_DEVICE *Device + ) +{ + BOOLEAN CurrentPresent; + BOOLEAN PreviousPresent; + + // + // eMMC is always present (embedded) + // + if (Device->IsEMMC) { + return EFI_SUCCESS; + } + + // + // For SD cards, check PRESENT_STATE register + // + UINT32 PresentState = SdhciReadl (Device, SDHCI_PRESENT_STATE); + CurrentPresent = (PresentState & SDHCI_CARD_PRESENT) != 0; + PreviousPresent = Device->BlockIoMedia.MediaPresent; + + // + // Check if media state changed + // + if (CurrentPresent != PreviousPresent) { + Device->BlockIoMedia.MediaPresent = CurrentPresent; + Device->BlockIoMedia.MediaId++; // Increment to indicate media change + + if (CurrentPresent) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Media status: inserted\n")); + } else { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Media status: removed\n")); + } + + return EFI_MEDIA_CHANGED; + } + + // + // No change, but check current state + // + if (!CurrentPresent) { + return EFI_NO_MEDIA; + } + + return EFI_SUCCESS; +} + +/** + Reset the block device. + + @param[in] This Pointer to the BLOCK_IO_PROTOCOL instance. + @param[in] ExtendedVerification Indicates extended verification is requested. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning correctly. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + SD_MMC_CB_DEVICE *Device; + EFI_STATUS Status; + + Device = SD_MMC_CB_DEVICE_FROM_BLOCK_IO (This); + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: BlockIoReset\n")); + + // + // Check media presence for removable media + // + Status = CheckMediaPresence (Device); + if (Status == EFI_NO_MEDIA) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Reset: No media present\n")); + return EFI_SUCCESS; // Reset succeeded, but no media + } + + // + // Reset the controller + // + return SdhciReset (Device, SDHCI_RESET_ALL); +} + +/** + Read blocks from the block device. + + @param[in] This Pointer to the BLOCK_IO_PROTOCOL instance. + @param[in] MediaId Media ID that the read request is for. + @param[in] Lba The starting logical block address to read from. + @param[in] BufferSize The size of the buffer in bytes. + @param[out] Buffer Pointer to the destination buffer. + + @retval EFI_SUCCESS The data was read correctly. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The buffer size is not a multiple of the block size. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + SD_MMC_CB_DEVICE *Device; + EFI_STATUS Status; + UINT32 BlockCount; + UINT32 Response[4]; + + Device = SD_MMC_CB_DEVICE_FROM_BLOCK_IO (This); + + // + // Check media presence (for removable media like SD cards) + // + Status = CheckMediaPresence (Device); + if (Status == EFI_MEDIA_CHANGED) { + return EFI_MEDIA_CHANGED; + } + if (Status == EFI_NO_MEDIA) { + return EFI_NO_MEDIA; + } + + // + // Validate MediaId + // + if (MediaId != Device->BlockIoMedia.MediaId) { + return EFI_MEDIA_CHANGED; + } + + // + // Validate parameters + // + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + if (BufferSize % Device->BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba + (BufferSize / Device->BlockSize) > Device->TotalBlocks) { + return EFI_INVALID_PARAMETER; + } + + BlockCount = BufferSize / Device->BlockSize; + + // Only log large transfers to reduce serial output overhead + if (BlockCount > 8) { + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: ReadBlocks LBA=%ld Count=%d Size=%d\n", + Lba, BlockCount, BufferSize)); + } + + // + // Calculate command argument based on addressing mode + // High capacity: block addressing (LBA) + // Low capacity: byte addressing (LBA * block size) + // + UINT32 CmdArg; + if (Device->HighCapacity) { + CmdArg = (UINT32)Lba; + } else { + CmdArg = (UINT32)(Lba * Device->BlockSize); + } + + // + // Use CMD17 (single block) or CMD18 (multiple blocks) + // + if (BlockCount == 1) { + Status = SdhciSendCommand ( + Device, + MMC_CMD_READ_SINGLE_BLOCK, + CmdArg, + MMC_RSP_R1, + Response, + Buffer, + Device->BlockSize, + 1, + TRUE + ); + } else { + Status = SdhciSendCommand ( + Device, + MMC_CMD_READ_MULTIPLE_BLOCK, + CmdArg, + MMC_RSP_R1, + Response, + Buffer, + Device->BlockSize, + BlockCount, + TRUE + ); + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Read failed: %r\n", Status)); + return EFI_DEVICE_ERROR; + } + + // DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Read successful\n")); + return EFI_SUCCESS; +} + +/** + Write blocks to the block device. + + @param[in] This Pointer to the BLOCK_IO_PROTOCOL instance. + @param[in] MediaId Media ID that the write request is for. + @param[in] Lba The starting logical block address to write to. + @param[in] BufferSize The size of the buffer in bytes. + @param[in] Buffer Pointer to the source buffer. + + @retval EFI_SUCCESS The data was written correctly. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The buffer size is not a multiple of the block size. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + SD_MMC_CB_DEVICE *Device; + EFI_STATUS Status; + UINT32 BlockCount; + UINT32 Response[4]; + + Device = SD_MMC_CB_DEVICE_FROM_BLOCK_IO (This); + + // + // Check media presence (for removable media like SD cards) + // + Status = CheckMediaPresence (Device); + if (Status == EFI_MEDIA_CHANGED) { + return EFI_MEDIA_CHANGED; + } + if (Status == EFI_NO_MEDIA) { + return EFI_NO_MEDIA; + } + + // + // Validate MediaId + // + if (MediaId != Device->BlockIoMedia.MediaId) { + return EFI_MEDIA_CHANGED; + } + + // + // Validate parameters + // + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + if (BufferSize % Device->BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba + (BufferSize / Device->BlockSize) > Device->TotalBlocks) { + return EFI_INVALID_PARAMETER; + } + + BlockCount = BufferSize / Device->BlockSize; + + // Only log large transfers to reduce serial output overhead + if (BlockCount > 8) { + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: WriteBlocks LBA=%ld Count=%d Size=%d\n", + Lba, BlockCount, BufferSize)); + } + + // + // Calculate command argument based on addressing mode + // High capacity: block addressing (LBA) + // Low capacity: byte addressing (LBA * block size) + // + UINT32 CmdArg; + if (Device->HighCapacity) { + CmdArg = (UINT32)Lba; + } else { + CmdArg = (UINT32)(Lba * Device->BlockSize); + } + + // + // Use CMD24 (single block) or CMD25 (multiple blocks) + // + if (BlockCount == 1) { + Status = SdhciSendCommand ( + Device, + MMC_CMD_WRITE_SINGLE_BLOCK, + CmdArg, + MMC_RSP_R1, + Response, + Buffer, + Device->BlockSize, + 1, + FALSE + ); + } else { + Status = SdhciSendCommand ( + Device, + MMC_CMD_WRITE_MULTIPLE_BLOCK, + CmdArg, + MMC_RSP_R1, + Response, + Buffer, + Device->BlockSize, + BlockCount, + FALSE + ); + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Write failed: %r\n", Status)); + return EFI_DEVICE_ERROR; + } + + // DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Write successful\n")); + return EFI_SUCCESS; +} + +/** + Flush the block device. + + @param[in] This Pointer to the BLOCK_IO_PROTOCOL instance. + + @retval EFI_SUCCESS All outstanding data was written to the device. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + // + // eMMC doesn't have a flush command, data is written immediately + // + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDiskInfo.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDiskInfo.c new file mode 100644 index 000000000000..69ea69950444 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDiskInfo.c @@ -0,0 +1,132 @@ +/** @file + Implements EFI Disk Info Protocol for SD/MMC devices. + + Based on MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDiskInfo.c + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ Copyright (c) 2024, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +/** + Provides inquiry information for the controller type. + + For SD/MMC, this returns the CID (Card Identification) data. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param[in, out] InquiryData Pointer to a buffer for the inquiry data. + @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough. + @retval EFI_INVALID_PARAMETER InquiryDataSize is NULL. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoInquiry ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *InquiryDataSize + ) +{ + EFI_STATUS Status; + SD_MMC_CB_DEVICE *Device; + UINT32 RequiredSize; + + Device = SD_MMC_CB_DEVICE_FROM_DISK_INFO (This); + + if (Device->IsEMMC) { + RequiredSize = sizeof (EMMC_CID); + } else { + RequiredSize = sizeof (SD_CID); + } + + if (*InquiryDataSize >= RequiredSize) { + Status = EFI_SUCCESS; + if (Device->IsEMMC) { + CopyMem (InquiryData, &Device->Cid.EmmcCid, sizeof (EMMC_CID)); + } else { + CopyMem (InquiryData, &Device->Cid.SdCid, sizeof (SD_CID)); + } + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *InquiryDataSize = RequiredSize; + + return Status; +} + +/** + Provides identify information for the controller type. + + Not used for SD/MMC. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param[in, out] IdentifyData Pointer to a buffer for the identify data. + @param[in, out] IdentifyDataSize Pointer to the value for the identify data size. + + @retval EFI_NOT_FOUND The device does not support this data class. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoIdentify ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ) +{ + return EFI_NOT_FOUND; +} + +/** + Provides sense data information for the controller type. + + Not used for SD/MMC. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param[out] SenseData Pointer to the SenseData. + @param[in, out] SenseDataSize Size of SenseData in bytes. + @param[out] SenseDataNumber Number of items in SenseData. + + @retval EFI_NOT_FOUND The device does not support this data class. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoSenseData ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ) +{ + return EFI_NOT_FOUND; +} + +/** + Provides IDE channel and device information for the IDE/ATAPI controller. + + Not used for SD/MMC. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param[out] IdeChannel Pointer to the IdeChannel. + @param[out] IdeDevice Pointer to the IdeDevice. + + @retval EFI_UNSUPPORTED This is not an IDE device. + +**/ +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoWhichIde ( + IN EFI_DISK_INFO_PROTOCOL *This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.c new file mode 100644 index 000000000000..881d4173b5dc --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.c @@ -0,0 +1,812 @@ +/** @file + Depthcharge-based SD/MMC PCI Host Controller Driver + Main driver entry point and PCI binding logic + + Copyright (c) 2025, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +// +// PCI Class codes +// +#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08 +#define PCI_SUBCLASS_SD_HOST_CONTROLLER 0x05 +#define PCI_BASE_ADDRESSREG_OFFSET 0x10 + +EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciCbDriverBinding = { + SdMmcPciCbDriverBindingSupported, + SdMmcPciCbDriverBindingStart, + SdMmcPciCbDriverBindingStop, + 0x10, + NULL, // ImageHandle - will be set in entry point + NULL // DriverBindingHandle - will be set in entry point +}; + +/** + Timer callback to check for SD card insertion/removal. + + @param[in] Event The timer event + @param[in] Context Pointer to SD_MMC_CB_DEVICE + +**/ +VOID +EFIAPI +MediaChangeTimerCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + SD_MMC_CB_DEVICE *Device; + UINT32 PresentState; + BOOLEAN CurrentPresent; + BOOLEAN PreviousPresent; + + Device = (SD_MMC_CB_DEVICE *)Context; + + // + // Only check for removable media (SD cards) + // + if (Device->IsEMMC) { + return; + } + + // + // Check if card is present + // + PresentState = SdhciReadl (Device, SDHCI_PRESENT_STATE); + CurrentPresent = (PresentState & SDHCI_CARD_PRESENT) != 0; + PreviousPresent = Device->BlockIoMedia.MediaPresent; + + // + // If media state changed, update and trigger reconnection + // + if (CurrentPresent != PreviousPresent) { + Device->BlockIoMedia.MediaPresent = CurrentPresent; + Device->BlockIoMedia.MediaId++; + + if (CurrentPresent) { + DEBUG ((DEBUG_INFO, "SdMmcCb: SD card inserted! MediaId=%d\n", Device->BlockIoMedia.MediaId)); + + // + // Re-initialize the SD card to get its capacity and parameters + // First, reset the controller to clear any stale state from previous card + // + SdhciReset (Device, SDHCI_RESET_ALL); + gBS->Stall (10000); // 10ms for reset to complete + + // Re-initialize the controller for the new card + EFI_STATUS Status = SdhciInit (Device); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcCb: SdhciInit failed during hot-plug: %r\n", Status)); + Device->BlockIoMedia.MediaPresent = FALSE; + Device->BlockIoMedia.LastBlock = 0; + } else { + // Now initialize the card + Status = SdStartup (Device); + if (!EFI_ERROR (Status)) { + // Update BlockIo media with new card's capacity + Device->BlockIoMedia.BlockSize = Device->BlockSize; + Device->BlockIoMedia.LastBlock = Device->TotalBlocks > 0 ? Device->TotalBlocks - 1 : 0; + DEBUG ((DEBUG_INFO, "SdMmcCb: SD card initialized: %lld blocks\n", Device->TotalBlocks)); + } else { + DEBUG ((DEBUG_ERROR, "SdMmcCb: SD card initialization failed: %r\n", Status)); + // Set media as not present if init fails + Device->BlockIoMedia.MediaPresent = FALSE; + Device->BlockIoMedia.LastBlock = 0; + } + } + } else { + DEBUG ((DEBUG_INFO, "SdMmcCb: SD card removed! MediaId=%d\n", Device->BlockIoMedia.MediaId)); + // Reset capacity when card is removed + Device->TotalBlocks = 0; + Device->BlockIoMedia.LastBlock = 0; + } + + // + // Reinstall BlockIo protocol to trigger BDS reconnection + // This makes the boot menu refresh automatically + // + gBS->ReinstallProtocolInterface ( + Device->ChildHandle, + &gEfiBlockIoProtocolGuid, + &Device->BlockIo, + &Device->BlockIo + ); + } +} + +/** + Test to see if this driver supports ControllerHandle. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +SdMmcPciCbDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 PciData; + + PciIo = NULL; + + //DEBUG ((DEBUG_INFO, "SdMmcPciCb: Supported() called\n")); + + // + // Open PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + //DEBUG ((DEBUG_WARN, "SdMmcPciCb: OpenProtocol failed: %r\n", Status)); + return Status; + } + + //DEBUG ((DEBUG_INFO, "SdMmcPciCb: OpenProtocol succeeded, reading PCI config...\n")); + + // + // Read PCI configuration space + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciData) / sizeof (UINT32), + &PciData + ); + if (EFI_ERROR (Status)) { + //DEBUG ((DEBUG_ERROR, "SdMmcPciCb: PCI read failed: %r\n", Status)); + goto Done; + } + + // + // Debug: Print every device we check + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Checking device %04x:%04x\n", + PciData.Hdr.VendorId, PciData.Hdr.DeviceId)); + + // + // Check if this is an SD Host Controller (Class 08, SubClass 05) + // This matches Depthcharge's approach: support ALL SDHCI controllers + // + if (PciData.Hdr.ClassCode[2] != PCI_CLASS_SYSTEM_PERIPHERAL || + PciData.Hdr.ClassCode[1] != PCI_SUBCLASS_SD_HOST_CONTROLLER) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + // + // This is an SDHCI controller - we support it! + // Same universal approach as Depthcharge's pci_sdhci.c + // + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Found SDHCI controller %04x:%04x (Class=%02x SubClass=%02x)\n", + PciData.Hdr.VendorId, PciData.Hdr.DeviceId, + PciData.Hdr.ClassCode[2], PciData.Hdr.ClassCode[1])); + + // + // Identify known controllers for informational purposes + // + if (PciData.Hdr.VendorId == 0x17a0) { + // Genesys Logic + if (PciData.Hdr.DeviceId == 0xe763) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: -> Genesys Logic GL9763E (eMMC)\n")); + } else if (PciData.Hdr.DeviceId == 0x9750) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: -> Genesys Logic GL9750 (SD)\n")); + } + } else if (PciData.Hdr.VendorId == 0x8086) { + // Intel integrated SDHCI + DEBUG ((DEBUG_INFO, "SdMmcPciCb: -> Intel integrated SDHCI\n")); + } else if (PciData.Hdr.VendorId == 0x1022) { + // AMD integrated SDHCI + DEBUG ((DEBUG_INFO, "SdMmcPciCb: -> AMD integrated SDHCI\n")); + } else if (PciData.Hdr.VendorId == 0x1217) { + // O2 Micro / BayHub (BH720 family) + DEBUG ((DEBUG_INFO, "SdMmcPciCb: -> BayHub/O2Micro SDHCI (generic mode)\n")); + } + + // + // Accept all SDHCI controllers (vendor quirks applied during Start) + // + Status = EFI_SUCCESS; + +Done: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Start this driver on ControllerHandle. + + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHandle. + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +SdMmcPciCbDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + SD_MMC_CB_DEVICE *Device; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 Supports; + UINTN MmioBase; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: DriverBindingStart called\n")); + + Device = NULL; + + // + // Open PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate device context + // + Device = AllocateZeroPool (sizeof (SD_MMC_CB_DEVICE)); + if (Device == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + Device->Signature = SD_MMC_CB_SIGNATURE; + Device->ControllerHandle = Controller; + Device->PciIo = PciIo; + + // + // Detect controller type + // + PCI_TYPE00 PciData; + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciData) / sizeof (UINT32), + &PciData + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Detect controller type and set quirk flags + // + Device->IsGL9763E = FALSE; + Device->IsGL9750 = FALSE; + + if (PciData.Hdr.VendorId == 0x17a0) { + // Genesys Logic controllers + if (PciData.Hdr.DeviceId == 0xe763) { + Device->IsGL9763E = TRUE; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Genesys Logic GL9763E detected (will apply L1 delay quirk)\n")); + } else if (PciData.Hdr.DeviceId == 0x9750) { + Device->IsGL9750 = TRUE; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Genesys Logic GL9750 detected\n")); + } + } + + // + // Auto-detect eMMC vs SD card after controller initialization + // For now, assume eMMC for GL9763E, SD for GL9750, and try eMMC first for unknown + // + if (Device->IsGL9763E) { + Device->IsEMMC = TRUE; // GL9763E is always eMMC + } else if (Device->IsGL9750) { + Device->IsEMMC = FALSE; // GL9750 is always SD + } else { + // Unknown controller - try eMMC first (most common in Chromebooks) + // If eMMC fails, could fall back to SD detection in future + Device->IsEMMC = TRUE; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Unknown SDHCI controller, assuming eMMC slot\n")); + } + + // + // Get device path from controller + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **)&Device->DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to get DevicePath: %r\n", Status)); + Device->DevicePath = NULL; + } + + // + // Enable PCI attributes + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationGet, + 0, + &Supports + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Get BAR0 (MMIO base) - Read directly from PCI config space + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + PCI_BASE_ADDRESSREG_OFFSET, + 1, + &MmioBase + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to read BAR0: %r\n", Status)); + goto Error; + } + + // + // Clear lower bits (memory type flags - bit 0=Memory Space Indicator, bits 1-2=Type, bit 3=Prefetchable) + // + MmioBase &= ~0xFULL; + + if (MmioBase == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: BAR0 is not assigned!\n")); + Status = EFI_DEVICE_ERROR; + goto Error; + } + + Device->MmioBase = (VOID *)MmioBase; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: MMIO Base = 0x%016lx\n", (UINT64)MmioBase)); + + // + // Read controller version and capabilities + // + Device->Version = SdhciReadw (Device, SDHCI_HOST_VERSION); + Device->Capabilities = SdhciReadl (Device, SDHCI_CAPABILITIES); + + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: GL9763E Controller initialized!\n")); + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: Version = 0x%04x\n", Device->Version)); + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: Capabilities = 0x%08x\n", Device->Capabilities)); + + // + // Phase 2: Initialize SDHCI controller + // + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Initializing SDHCI controller...\n")); + Status = SdhciInit (Device); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: SdhciInit failed: %r\n", Status)); + goto Error; + } + + // + // Phase 3: Initialize card (eMMC or SD) + // + if (Device->IsEMMC) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Initializing eMMC device...\n")); + Status = MmcStartup (Device); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: MmcStartup failed: %r\n", Status)); + goto Error; + } + } else { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Initializing SD card...\n")); + Status = SdStartup (Device); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: SdStartup failed: %r\n", Status)); + // SD card might not be inserted - this is OK for removable media + // Set defaults and continue (BlockIo will report no media) + Device->BlockSize = 512; + Device->TotalBlocks = 0; + Device->HighCapacity = TRUE; + Device->BlockIoMedia.MediaPresent = FALSE; + DEBUG ((DEBUG_WARN, "SdMmcPciCb: No SD card present or initialization failed\n")); + } + } + + // + // Phase 4: Install BlockIo Protocol + // + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Installing BlockIo protocol...\n")); + + // + // Initialize BlockIo Media + // + Device->BlockIoMedia.MediaId = 0; + Device->BlockIoMedia.RemovableMedia = !Device->IsEMMC; // SD cards are removable + Device->BlockIoMedia.MediaPresent = TRUE; // Assume present (updated during init if failed) + Device->BlockIoMedia.LogicalPartition = FALSE; + Device->BlockIoMedia.ReadOnly = FALSE; + Device->BlockIoMedia.WriteCaching = FALSE; + Device->BlockIoMedia.BlockSize = Device->BlockSize; + Device->BlockIoMedia.IoAlign = 4; // 32-bit aligned + Device->BlockIoMedia.LastBlock = Device->TotalBlocks > 0 ? Device->TotalBlocks - 1 : 0; + + // + // Initialize BlockIo Protocol + // + Device->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3; + Device->BlockIo.Media = &Device->BlockIoMedia; + Device->BlockIo.Reset = SdMmcDcBlockIoReset; + Device->BlockIo.ReadBlocks = SdMmcDcBlockIoReadBlocks; + Device->BlockIo.WriteBlocks = SdMmcDcBlockIoWriteBlocks; + Device->BlockIo.FlushBlocks = SdMmcDcBlockIoFlushBlocks; + + // + // Initialize DiskInfo Protocol + // + if (Device->IsEMMC) { + CopyGuid (&Device->DiskInfo.Interface, &gEfiDiskInfoSdMmcInterfaceGuid); + } else { + CopyGuid (&Device->DiskInfo.Interface, &gEfiDiskInfoSdMmcInterfaceGuid); + } + Device->DiskInfo.Inquiry = SdMmcDcDiskInfoInquiry; + Device->DiskInfo.Identify = SdMmcDcDiskInfoIdentify; + Device->DiskInfo.SenseData = SdMmcDcDiskInfoSenseData; + Device->DiskInfo.WhichIde = SdMmcDcDiskInfoWhichIde; + + // + // Create device path for the card device + // The parent controller should have a device path; we append an SD/eMMC node to it + // + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath = NULL; + if (Device->DevicePath != NULL) { + if (Device->IsEMMC) { + // Use MSG_EMMC_DP for eMMC to get "Internal eMMC" naming in BDS + EMMC_DEVICE_PATH EmmcNode; + + EmmcNode.Header.Type = MESSAGING_DEVICE_PATH; + EmmcNode.Header.SubType = MSG_EMMC_DP; + SetDevicePathNodeLength (&EmmcNode.Header, sizeof (EMMC_DEVICE_PATH)); + EmmcNode.SlotNumber = 0; // Single eMMC device on this controller + + NewDevicePath = AppendDevicePathNode (Device->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&EmmcNode); + } else { + // Use MSG_SD_DP for SD card + SD_DEVICE_PATH SdNode; + + SdNode.Header.Type = MESSAGING_DEVICE_PATH; + SdNode.Header.SubType = MSG_SD_DP; + SetDevicePathNodeLength (&SdNode.Header, sizeof (SD_DEVICE_PATH)); + SdNode.SlotNumber = 0; + + NewDevicePath = AppendDevicePathNode (Device->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&SdNode); + } + + if (NewDevicePath == NULL) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to create device path\n")); + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + } + + // + // Install BlockIo, DiskInfo, and DevicePath Protocols on child handle + // + Device->ChildHandle = NULL; + if (NewDevicePath != NULL) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &Device->ChildHandle, + &gEfiDevicePathProtocolGuid, + NewDevicePath, + &gEfiBlockIoProtocolGuid, + &Device->BlockIo, + &gEfiDiskInfoProtocolGuid, + &Device->DiskInfo, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &Device->ChildHandle, + &gEfiBlockIoProtocolGuid, + &Device->BlockIo, + &gEfiDiskInfoProtocolGuid, + &Device->DiskInfo, + NULL + ); + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to install BlockIo: %r\n", Status)); + if (NewDevicePath != NULL) { + FreePool (NewDevicePath); + } + goto Error; + } + + // + // Open PciIo protocol BY_CHILD_CONTROLLER + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, + This->DriverBindingHandle, + Device->ChildHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to open PciIo BY_CHILD: %r\n", Status)); + gBS->UninstallMultipleProtocolInterfaces ( + Device->ChildHandle, + &gEfiBlockIoProtocolGuid, + &Device->BlockIo, + &gEfiDiskInfoProtocolGuid, + &Device->DiskInfo, + NULL + ); + goto Error; + } + + if (Device->IsEMMC) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Driver start complete! eMMC initialized successfully!\n")); + } else { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Driver start complete! SD card reader ready!\n")); + + // + // For removable media (SD cards), create a timer to poll for media changes + // This allows automatic boot menu refresh when cards are inserted/removed + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + MediaChangeTimerCallback, + Device, // Pass device context to callback + &Device->MediaChangeEvent + ); + if (!EFI_ERROR (Status)) { + // Poll every 100ms (same as standard driver) + Status = gBS->SetTimer ( + Device->MediaChangeEvent, + TimerPeriodic, + 1000000 // 100ms in 100ns units + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (Device->MediaChangeEvent); + Device->MediaChangeEvent = NULL; + } else { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Media change polling enabled (100ms)\n")); + } + } + } + DEBUG ((DEBUG_INFO, "SdMmcPciCb: BlockIo installed on handle %p\n", Device->ChildHandle)); + + return EFI_SUCCESS; + +Error: + if (Device != NULL) { + FreePool (Device); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Stop this driver on ControllerHandle. + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on. + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle. + @retval other This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +SdMmcPciCbDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + SD_MMC_CB_DEVICE *Device; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (NumberOfChildren == 0) { + // + // Close PciIo protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + // + // Get BlockIo protocol from child handle + // + Status = gBS->OpenProtocol ( + ChildHandleBuffer[0], + &gEfiBlockIoProtocolGuid, + (VOID **)&BlockIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Device = SD_MMC_CB_DEVICE_FROM_BLOCK_IO (BlockIo); + + // + // Get device path to free it later + // + Status = gBS->OpenProtocol ( + ChildHandleBuffer[0], + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + // + // Close PciIo protocol opened BY_CHILD_CONTROLLER + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[0] + ); + + // + // Uninstall protocols from child handle + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[0], + &gEfiBlockIoProtocolGuid, + &Device->BlockIo, + &gEfiDiskInfoProtocolGuid, + &Device->DiskInfo, + &gEfiDevicePathProtocolGuid, + DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Free device path + // + if (DevicePath != NULL) { + FreePool (DevicePath); + } + + // + // Stop and close media change timer if it exists (for SD cards) + // + if (Device->MediaChangeEvent != NULL) { + gBS->SetTimer (Device->MediaChangeEvent, TimerCancel, 0); + gBS->CloseEvent (Device->MediaChangeEvent); + Device->MediaChangeEvent = NULL; + } + + // + // Free ADMA descriptors if allocated + // + if (Device->AdmaDescs != NULL) { + FreePool (Device->AdmaDescs); + } + if (Device->Adma64Descs != NULL) { + FreePool (Device->Adma64Descs); + } + + // + // Free device structure + // + FreePool (Device); + + return EFI_SUCCESS; +} + +/** + Driver entry point. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The driver was initialized successfully. + +**/ +EFI_STATUS +EFIAPI +InitializeSdMmcPciCbDxe ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Depthcharge-based SDHCI Driver Loading...\n")); + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gSdMmcPciCbDriverBinding, + ImageHandle, + &gSdMmcPciCbComponentName, + &gSdMmcPciCbComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Driver installed, Status = %r\n", Status)); + + return Status; +} + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.h b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.h new file mode 100644 index 000000000000..3015e70b490f --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.h @@ -0,0 +1,657 @@ +/** @file + Depthcharge-based SD/MMC PCI Host Controller Driver Header + Register definitions and structures ported from Depthcharge + + Copyright (c) 2025, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SD_MMC_PCI_DC_DXE_H_ +#define _SD_MMC_PCI_DC_DXE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciCbComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gSdMmcPciCbComponentName2; +extern EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciCbDriverBinding; + +// +// SDHCI Register Definitions (from Depthcharge sdhci.h) +// + +#define SDHCI_DMA_ADDRESS 0x00 + +#define SDHCI_BLOCK_SIZE 0x04 +#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) + +#define SDHCI_BLOCK_COUNT 0x06 + +#define SDHCI_ARGUMENT 0x08 + +#define SDHCI_TRANSFER_MODE 0x0C +#define SDHCI_TRNS_DMA 0x01 +#define SDHCI_TRNS_BLK_CNT_EN 0x02 +#define SDHCI_TRNS_ACMD12 0x04 +#define SDHCI_TRNS_READ 0x10 +#define SDHCI_TRNS_MULTI 0x20 + +#define SDHCI_COMMAND 0x0E +#define SDHCI_CMD_RESP_MASK 0x03 +#define SDHCI_CMD_CRC 0x08 +#define SDHCI_CMD_INDEX 0x10 +#define SDHCI_CMD_DATA 0x20 +#define SDHCI_CMD_ABORTCMD 0xC0 + +#define SDHCI_CMD_RESP_NONE 0x00 +#define SDHCI_CMD_RESP_LONG 0x01 +#define SDHCI_CMD_RESP_SHORT 0x02 +#define SDHCI_CMD_RESP_SHORT_BUSY 0x03 + +#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff)) +#define SDHCI_GET_CMD(c) ((c>>8) & 0x3f) + +#define SDHCI_RESPONSE 0x10 + +#define SDHCI_BUFFER 0x20 + +#define SDHCI_PRESENT_STATE 0x24 +#define SDHCI_CMD_INHIBIT 0x00000001 +#define SDHCI_DATA_INHIBIT 0x00000002 +#define SDHCI_DOING_WRITE 0x00000100 +#define SDHCI_DOING_READ 0x00000200 +#define SDHCI_SPACE_AVAILABLE 0x00000400 +#define SDHCI_DATA_AVAILABLE 0x00000800 +#define SDHCI_CARD_PRESENT 0x00010000 +#define SDHCI_CARD_STATE_STABLE 0x00020000 +#define SDHCI_CARD_DETECT_PIN_LEVEL 0x00040000 +#define SDHCI_WRITE_PROTECT 0x00080000 + +#define SDHCI_HOST_CONTROL 0x28 +#define SDHCI_CTRL_LED 0x01 +#define SDHCI_CTRL_4BITBUS 0x02 +#define SDHCI_CTRL_HISPD 0x04 +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_CTRL_ADMA1 0x08 +#define SDHCI_CTRL_ADMA32 0x10 +#define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_8BITBUS 0x20 +#define SDHCI_CTRL_CD_TEST_INS 0x40 +#define SDHCI_CTRL_CD_TEST 0x80 + +#define SDHCI_POWER_CONTROL 0x29 +#define SDHCI_POWER_ON 0x01 +#define SDHCI_POWER_180 0x0A +#define SDHCI_POWER_300 0x0C +#define SDHCI_POWER_330 0x0E + +#define SDHCI_BLOCK_GAP_CONTROL 0x2A + +#define SDHCI_WAKE_UP_CONTROL 0x2B +#define SDHCI_WAKE_ON_INT 0x01 +#define SDHCI_WAKE_ON_INSERT 0x02 +#define SDHCI_WAKE_ON_REMOVE 0x04 + +#define SDHCI_CLOCK_CONTROL 0x2C +#define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF +#define SDHCI_DIV_MASK_LEN 8 +#define SDHCI_DIV_HI_MASK 0x300 +#define SDHCI_CLOCK_CARD_EN 0x0004 +#define SDHCI_CLOCK_INT_STABLE 0x0002 +#define SDHCI_CLOCK_INT_EN 0x0001 + +#define SDHCI_TIMEOUT_CONTROL 0x2E + +#define SDHCI_SOFTWARE_RESET 0x2F +#define SDHCI_RESET_ALL 0x01 +#define SDHCI_RESET_CMD 0x02 +#define SDHCI_RESET_DATA 0x04 + +#define SDHCI_INT_STATUS 0x30 +#define SDHCI_INT_ENABLE 0x34 +#define SDHCI_SIGNAL_ENABLE 0x38 +#define SDHCI_INT_RESPONSE 0x00000001 +#define SDHCI_INT_DATA_END 0x00000002 +#define SDHCI_INT_DMA_END 0x00000008 +#define SDHCI_INT_SPACE_AVAIL 0x00000010 +#define SDHCI_INT_DATA_AVAIL 0x00000020 +#define SDHCI_INT_CARD_INSERT 0x00000040 +#define SDHCI_INT_CARD_REMOVE 0x00000080 +#define SDHCI_INT_CARD_INT 0x00000100 +#define SDHCI_INT_ERROR 0x00008000 +#define SDHCI_INT_TIMEOUT 0x00010000 +#define SDHCI_INT_CRC 0x00020000 +#define SDHCI_INT_END_BIT 0x00040000 +#define SDHCI_INT_INDEX 0x00080000 +#define SDHCI_INT_DATA_TIMEOUT 0x00100000 +#define SDHCI_INT_DATA_CRC 0x00200000 +#define SDHCI_INT_DATA_END_BIT 0x00400000 +#define SDHCI_INT_BUS_POWER 0x00800000 +#define SDHCI_INT_ACMD12ERR 0x01000000 +#define SDHCI_INT_ADMA_ERROR 0x02000000 + +#define SDHCI_INT_NORMAL_MASK 0x00007FFF +#define SDHCI_INT_ERROR_MASK 0xFFFF8000 + +#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ + SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) +#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ + SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ + SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ + SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR) +#define SDHCI_INT_ALL_MASK ((UINT32)-1) + +#define SDHCI_ACMD12_ERR 0x3C + +#define SDHCI_HOST_CONTROL2 0x3E +#define SDHCI_CTRL_UHS_MASK 0x0007 +#define SDHCI_CTRL_UHS_SDR12 0x0000 +#define SDHCI_CTRL_UHS_SDR25 0x0001 +#define SDHCI_CTRL_UHS_SDR50 0x0002 +#define SDHCI_CTRL_UHS_SDR104 0x0003 +#define SDHCI_CTRL_UHS_DDR50 0x0004 +#define SDHCI_CTRL_HS400 0x0005 +#define SDHCI_CTRL_180V_SIGNALING_ENABLE 0x0008 +#define SDHCI_CTRL_DRV_TYPE_SHIFT 4 +#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 +#define SDHCI_CTRL_DRV_TYPE_B 0x0000 +#define SDHCI_CTRL_DRV_TYPE_A 0x0010 +#define SDHCI_CTRL_DRV_TYPE_C 0x0020 +#define SDHCI_CTRL_DRV_TYPE_D 0x0030 +#define SDHCI_CTRL_EXEC_TUNING 0x0040 +#define SDHCI_CTRL_TUNED_CLK 0x0080 +#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 + +#define SDHCI_CAPABILITIES 0x40 +#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F +#define SDHCI_TIMEOUT_CLK_SHIFT 0 +#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 +#define SDHCI_CLOCK_BASE_MASK 0x00003F00 +#define SDHCI_CLOCK_V3_BASE_MASK 0x0000FF00 +#define SDHCI_CLOCK_BASE_SHIFT 8 +#define SDHCI_MAX_BLOCK_MASK 0x00030000 +#define SDHCI_MAX_BLOCK_SHIFT 16 +#define SDHCI_CAN_DO_8BIT 0x00040000 +#define SDHCI_CAN_DO_ADMA2 0x00080000 +#define SDHCI_CAN_DO_ADMA1 0x00100000 +#define SDHCI_CAN_DO_HISPD 0x00200000 +#define SDHCI_CAN_DO_SDMA 0x00400000 +#define SDHCI_CAN_VDD_330 0x01000000 +#define SDHCI_CAN_VDD_300 0x02000000 +#define SDHCI_CAN_VDD_180 0x04000000 +#define SDHCI_CAN_64BIT 0x10000000 + +#define SDHCI_CAPABILITIES_1 0x44 +#define SDHCI_SUPPORT_SDR50 0x00000001 +#define SDHCI_SUPPORT_SDR104 0x00000002 +#define SDHCI_SUPPORT_DDR50 0x00000004 +#define SDHCI_SUPPORT_HS400 0x80000000 + +#define SDHCI_MAX_CURRENT 0x48 + +#define SDHCI_SET_ACMD12_ERROR 0x50 +#define SDHCI_SET_INT_ERROR 0x52 + +#define SDHCI_ADMA_ERROR 0x54 + +#define SDHCI_ADMA_ADDRESS 0x58 +#define SDHCI_ADMA_ADDRESS_HI 0x5C + +// +// ADMA descriptor attributes (from Depthcharge) +// +#define SDHCI_ADMA_VALID 0x01 +#define SDHCI_ADMA_END 0x02 +#define SDHCI_ADMA_INT 0x04 +#define SDHCI_ACT_NOP (0 << 4) +#define SDHCI_ACT_TRAN (2 << 4) +#define SDHCI_ACT_LINK (3 << 4) +#define SDHCI_MAX_PER_DESCRIPTOR 0x10000 // 64KB max per descriptor + +#define SDHCI_SLOT_INT_STATUS 0xFC + +#define SDHCI_HOST_VERSION 0xFE +#define SDHCI_VENDOR_VER_MASK 0xFF00 +#define SDHCI_VENDOR_VER_SHIFT 8 +#define SDHCI_SPEC_VER_MASK 0x00FF +#define SDHCI_SPEC_VER_SHIFT 0 +#define SDHCI_SPEC_100 0 +#define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 + +// +// GL9763E Vendor Registers (from Linux gl9763e.c and Depthcharge sdhci_gli.c) +// + +#define GLI_CFG_REG_1 0x844 +#define GLI_CFG_REG_2 0x8A4 +#define GLI_CFG_REG_2_L0S 0x00000001 +#define GLI_CFG_REG_2_L1DLY_MASK 0x1FF80000 +#define GLI_CFG_REG_2_L1DLY_SHIFT 19 +#define GLI_CFG_REG_2_L1DLY_MAX 0x1FF + +#define GLI_VENDOR_HS400_MODE 0x880 +#define GLI_HS400_ES_VENDOR 0x08000000 + +// GL9763E eMMC Control register for Enhanced Strobe +#define GL9763E_SDHC_EMMC_CTRL 0x52C +#define GL9763E_ENHANCED_STROBE 0x00000100 // Bit 8 + +// +// MMC Command Definitions (from Depthcharge mmc.h) +// + +#define MMC_CMD_GO_IDLE_STATE 0 +#define MMC_CMD_SEND_OP_COND 1 +#define MMC_CMD_ALL_SEND_CID 2 +#define MMC_CMD_SET_RELATIVE_ADDR 3 +#define MMC_CMD_SWITCH 6 +#define MMC_CMD_SELECT_CARD 7 +#define MMC_CMD_SEND_EXT_CSD 8 +#define MMC_CMD_SEND_STATUS 13 +#define MMC_CMD_SET_BLOCKLEN 16 +#define MMC_CMD_READ_SINGLE_BLOCK 17 +#define MMC_CMD_READ_MULTIPLE_BLOCK 18 +#define MMC_CMD_WRITE_SINGLE_BLOCK 24 +#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25 + +// +// SD Command Definitions +// +#define SD_CMD_SEND_IF_COND 8 // CMD8 +#define SD_CMD_SEND_CSD 9 // CMD9 +#define SD_VOLTAGE_SWITCH 11 // CMD11 (UHS-I voltage switch) +#define SD_CMD_APP_CMD 55 // CMD55 (precedes ACMD) +#define SD_CMD_READ_OCR 58 // CMD58 + +// SD Application Commands (preceded by CMD55) +#define SD_ACMD_SET_BUS_WIDTH 6 // ACMD6 +#define SD_ACMD_SD_STATUS 13 // ACMD13 +#define SD_ACMD_SEND_OP_COND 41 // ACMD41 + +// SD CMD8 argument +#define SD_CMD8_VHS_27_36 0x00000100 // 2.7-3.6V +#define SD_CMD8_CHECK_PATTERN 0x000000AA + +// SD ACMD41 argument +#define SD_OCR_VDD_32_33 0x00200000 +#define SD_OCR_HCS 0x40000000 // High Capacity Support +#define SD_OCR_XPC 0x10000000 // SDXC Power Control +#define SD_OCR_S18R 0x01000000 // 1.8V switching request + +// OCR (Operating Conditions Register) bits +#define OCR_BUSY 0x80000000 +#define OCR_HCS 0x40000000 // High Capacity Support +#define OCR_VOLTAGE_MASK 0x00FFFF80 + +// Card status bits (R1 response) +#define MMC_STATUS_RDY_FOR_DATA 0x00000100 +#define MMC_STATUS_CURR_STATE 0x00001E00 +#define MMC_STATUS_ERROR 0xFDFFE008 + +// EXT_CSD fields (from Depthcharge) +#define EXT_CSD_BUS_WIDTH 183 +#define EXT_CSD_STROBE_SUPPORT 184 // Enhanced Strobe support +#define EXT_CSD_HS_TIMING 185 +#define EXT_CSD_CARD_TYPE 196 +#define EXT_CSD_REV 192 +#define EXT_CSD_SEC_CNT 212 +#define EXT_CSD_SIZE 512 + +// EXT_CSD BUS_WIDTH values +#define EXT_CSD_BUS_WIDTH_1 0 +#define EXT_CSD_BUS_WIDTH_4 1 +#define EXT_CSD_BUS_WIDTH_8 2 + +// EXT_CSD HS_TIMING values +#define EXT_CSD_TIMING_LEGACY 0 +#define EXT_CSD_TIMING_HS 1 +#define EXT_CSD_TIMING_HS200 2 +#define EXT_CSD_TIMING_HS400 3 + +// EXT_CSD BUS_WIDTH DDR values +#define EXT_CSD_DDR_BUS_WIDTH_4 5 +#define EXT_CSD_DDR_BUS_WIDTH_8 6 + +// EXT_CSD BUS_WIDTH Enhanced Strobe bit (OR with DDR width) +#define EXT_CSD_BUS_WIDTH_STROBE 0x80 + +// EXT_CSD CARD_TYPE bits +#define EXT_CSD_CARD_TYPE_26 0x01 +#define EXT_CSD_CARD_TYPE_52 0x02 +#define EXT_CSD_CARD_TYPE_HS200_1_8V 0x10 +#define EXT_CSD_CARD_TYPE_HS400_1_8V 0x40 + +// MMC_SWITCH mode +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 + +// Data flags +#define MMC_DATA_READ 1 +#define MMC_DATA_WRITE 2 + +// Response types +#define MMC_RSP_PRESENT (1 << 0) +#define MMC_RSP_136 (1 << 1) +#define MMC_RSP_CRC (1 << 2) +#define MMC_RSP_BUSY (1 << 3) +#define MMC_RSP_OPCODE (1 << 4) + +#define MMC_RSP_NONE (0) +#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) +#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY) +#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC) +#define MMC_RSP_R3 (MMC_RSP_PRESENT) +#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) // SD: Published RCA +#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) // SD: Card interface condition + +// +// EDK2 Device Context +// + +// +// ADMA descriptor structures (from Depthcharge) +// +#pragma pack(1) +typedef struct { + UINT16 Attributes; + UINT16 Length; + UINT32 Address; +} SDHCI_ADMA_DESC; + +typedef struct { + UINT16 Attributes; + UINT16 Length; + UINT32 Address; + UINT32 AddressHi; +} SDHCI_ADMA64_DESC; +#pragma pack() + +#define SD_MMC_CB_SIGNATURE SIGNATURE_32 ('S', 'D', 'D', 'C') + +typedef struct { + UINT32 Signature; + EFI_HANDLE ControllerHandle; + EFI_HANDLE ChildHandle; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_BLOCK_IO_MEDIA BlockIoMedia; + EFI_DISK_INFO_PROTOCOL DiskInfo; + + // SDHCI controller info + VOID *MmioBase; + UINT32 Capabilities; + UINT32 Version; + UINT32 ClockBase; + UINT32 CurrentClock; + BOOLEAN Initialized; + + // eMMC/SD device info + UINT32 RelativeCardAddress; + UINT32 BlockSize; + UINT64 TotalBlocks; + BOOLEAN HighCapacity; // Block addressing vs byte addressing + + // Card Identification Data (structured, for DiskInfo) + union { + EMMC_CID EmmcCid; + SD_CID SdCid; + } Cid; + + // Genesys Logic specific + BOOLEAN IsGL9763E; // eMMC controller + BOOLEAN IsGL9750; // SD controller + BOOLEAN IsEMMC; // TRUE for eMMC, FALSE for SD card + + // Media change detection for removable media + EFI_EVENT MediaChangeEvent; // Timer for polling + + // ADMA support + SDHCI_ADMA_DESC *AdmaDescs; + SDHCI_ADMA64_DESC *Adma64Descs; + UINT32 AdmaDescCount; + BOOLEAN UseDma64; +} SD_MMC_CB_DEVICE; + +#define SD_MMC_CB_DEVICE_FROM_BLOCK_IO(a) \ + CR(a, SD_MMC_CB_DEVICE, BlockIo, SD_MMC_CB_SIGNATURE) + +#define SD_MMC_CB_DEVICE_FROM_DISK_INFO(a) \ + CR(a, SD_MMC_CB_DEVICE, DiskInfo, SD_MMC_CB_SIGNATURE) + +// +// Driver Binding Protocol +// + +extern EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciCbDriverBinding; + +// +// Function Prototypes +// + +// From SdMmcPciCbDxe.c +EFI_STATUS +EFIAPI +SdMmcPciCbDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +SdMmcPciCbDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +SdMmcPciCbDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// From SdMmcPciCbSdhci.c +EFI_STATUS +SdhciReset ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT8 Mask + ); + +EFI_STATUS +SdhciSetPower ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT8 PowerMode + ); + +EFI_STATUS +SdhciSetClock ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT32 Clock + ); + +EFI_STATUS +SdhciSendCommand ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT32 Cmd, + IN UINT32 Arg, + IN UINT32 ResponseType, + OUT UINT32 *Response, + IN VOID *DataBuffer OPTIONAL, + IN UINT32 BlockSize OPTIONAL, + IN UINT32 BlockCount OPTIONAL, + IN BOOLEAN IsRead OPTIONAL + ); + +EFI_STATUS +SdhciInit ( + IN SD_MMC_CB_DEVICE *Device + ); + +EFI_STATUS +SdhciSetupAdma ( + IN SD_MMC_CB_DEVICE *Device, + IN VOID *DataBuffer, + IN UINT32 TotalBytes, + IN BOOLEAN IsRead + ); + +EFI_STATUS +SdhciCompleteAdma ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT32 TimeoutMs + ); + +// From SdMmcPciCbMmc.c +EFI_STATUS +MmcStartup ( + IN SD_MMC_CB_DEVICE *Device + ); + +// From SdMmcPciCbSd.c +EFI_STATUS +SdStartup ( + IN SD_MMC_CB_DEVICE *Device + ); + +// From SdMmcPciCbGli.c +EFI_STATUS +Gl9763eInit ( + IN SD_MMC_CB_DEVICE *Device + ); + +VOID +Gl9763eSetEnhancedStrobe ( + IN SD_MMC_CB_DEVICE *Device, + IN BOOLEAN Enable + ); + +// From SdMmcPciCbBlockIo.c +EFI_STATUS +EFIAPI +SdMmcDcBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS +EFIAPI +SdMmcDcBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +SdMmcDcBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +SdMmcDcBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +// Helper macros for register access +#define SdhciReadl(Device, Reg) \ + *(volatile UINT32 *)((UINTN)(Device)->MmioBase + (Reg)) + +#define SdhciWritel(Device, Reg, Val) \ + *(volatile UINT32 *)((UINTN)(Device)->MmioBase + (Reg)) = (Val) + +#define SdhciReadw(Device, Reg) \ + *(volatile UINT16 *)((UINTN)(Device)->MmioBase + (Reg)) + +#define SdhciWritew(Device, Reg, Val) \ + *(volatile UINT16 *)((UINTN)(Device)->MmioBase + (Reg)) = (Val) + +#define SdhciReadb(Device, Reg) \ + *(volatile UINT8 *)((UINTN)(Device)->MmioBase + (Reg)) + +#define SdhciWriteb(Device, Reg, Val) \ + *(volatile UINT8 *)((UINTN)(Device)->MmioBase + (Reg)) = (Val) + +EFI_STATUS +EFIAPI +SdMmcPciCbComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +SdMmcPciCbComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// DiskInfo Protocol functions +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoInquiry ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *InquiryDataSize + ); + +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoIdentify ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ); + +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoSenseData ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ); + +EFI_STATUS +EFIAPI +SdMmcDcDiskInfoWhichIde ( + IN EFI_DISK_INFO_PROTOCOL *This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ); + +#endif // _SD_MMC_PCI_DC_DXE_H_ + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.inf b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.inf new file mode 100644 index 000000000000..65d8478dccb8 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.inf @@ -0,0 +1,58 @@ +## @file +# Depthcharge-based SD/MMC PCI Host Controller Driver +# Universal SDHCI 3.0+ driver for Chromebook eMMC and SD controllers +# +# This driver implements a complete port of Depthcharge's proven SDHCI/MMC stack +# to EDK2. It supports ALL standard SDHCI 3.0+ controllers (Class 08, SubClass 05), +# including Intel integrated controllers and Genesys Logic discrete controllers. +# +# Vendor-specific quirks (e.g., GL9763E L1 delay) are applied automatically. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SdMmcPciCbDxe + MODULE_UNI_FILE = SdMmcPciCbDxe.uni + FILE_GUID = 2b3c4d5e-6f70-8091-a2b3-c4d5e6f70809 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeSdMmcPciCbDxe + +[Sources] + SdMmcPciCbDxe.h + SdMmcPciCbDxe.c + SdMmcPciCbSdhci.c + SdMmcPciCbMmc.c + SdMmcPciCbSd.c + SdMmcPciCbGli.c + SdMmcPciCbBlockIo.c + SdMmcPciCbDiskInfo.c + ComponentName.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + DevicePathLib + +[Protocols] + gEfiPciIoProtocolGuid ## TO_START + gEfiBlockIoProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## BY_START + gEfiDiskInfoProtocolGuid ## BY_START + gEfiDriverBindingProtocolGuid ## PRODUCES + +[Guids] + gEfiDiskInfoSdMmcInterfaceGuid ## SOMETIMES_CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + SdMmcPciCbDxeExtra.uni + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.uni b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.uni new file mode 100644 index 000000000000..5e7abf72b9c5 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.uni @@ -0,0 +1,12 @@ +// /** @file +// Depthcharge-based SD/MMC PCI Host Controller Driver +// +// Copyright (c) 2025, Matt DeVillier. All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Depthcharge-based SD/MMC PCI Host Controller Driver" + +#string STR_MODULE_DESCRIPTION #language en-US "Complete port of Depthcharge's SDHCI driver for GL9763E support" + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxeExtra.uni b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxeExtra.uni new file mode 100644 index 000000000000..65db7375d66d --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxeExtra.uni @@ -0,0 +1,10 @@ +// /** @file +// Depthcharge-based SD/MMC PCI Host Controller Driver - Extra strings +// +// Copyright (c) 2025, Matt DeVillier. All rights reserved. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME #language en-US "Depthcharge SD/MMC PCI Host Controller Driver" + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbGli.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbGli.c new file mode 100644 index 000000000000..271ba03c9e73 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbGli.c @@ -0,0 +1,116 @@ +/** @file + GL9763E-specific initialization (ported from Depthcharge sdhci_gli.c) + + Copyright (c) 2025, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +/** + Initialize GL9763E vendor-specific registers. + + @param[in] Device Device context + + @retval EFI_SUCCESS Initialization successful +**/ +EFI_STATUS +Gl9763eInit ( + IN SD_MMC_CB_DEVICE *Device + ) +{ + EFI_STATUS Status; + UINT32 Value; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Gl9763eInit start\n")); + + // + // Configure CFG_REG_2: Disable L0s and set L1 entry delay + // This matches what the Linux driver does + // + Status = Device->PciIo->Pci.Read ( + Device->PciIo, + EfiPciIoWidthUint32, + GLI_CFG_REG_2, + 1, + &Value + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to read CFG_REG_2: %r\n", Status)); + return Status; + } + + // + // Disable L0s + // + Value &= ~GLI_CFG_REG_2_L0S; + + // + // Set L1 delay to 84 units (0x54) to match Linux and working coreboot config + // + Value &= ~(GLI_CFG_REG_2_L1DLY_MASK); + Value |= (0x54 << GLI_CFG_REG_2_L1DLY_SHIFT); + + Status = Device->PciIo->Pci.Write ( + Device->PciIo, + EfiPciIoWidthUint32, + GLI_CFG_REG_2, + 1, + &Value + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to write CFG_REG_2: %r\n", Status)); + return Status; + } + + // + // Read back to verify + // + Status = Device->PciIo->Pci.Read ( + Device->PciIo, + EfiPciIoWidthUint32, + GLI_CFG_REG_2, + 1, + &Value + ); + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Gl9763eInit complete\n")); + + return EFI_SUCCESS; +} + +/** + Enable or disable Enhanced Strobe for HS400-ES mode. + Based on Depthcharge's gl9763e_set_ios(). + + @param[in] Device Device context + @param[in] Enable TRUE to enable Enhanced Strobe, FALSE to disable +**/ +VOID +Gl9763eSetEnhancedStrobe ( + IN SD_MMC_CB_DEVICE *Device, + IN BOOLEAN Enable + ) +{ + UINT32 Ctrl; + + // + // Read current EMMC_CTRL register value + // + Ctrl = SdhciReadl (Device, GL9763E_SDHC_EMMC_CTRL); + + if (Enable) { + Ctrl |= GL9763E_ENHANCED_STROBE; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: GL9763E Enhanced Strobe enabled\n")); + } else { + Ctrl &= ~GL9763E_ENHANCED_STROBE; + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: GL9763E Enhanced Strobe disabled\n")); + } + + // + // Write updated value back + // + SdhciWritel (Device, GL9763E_SDHC_EMMC_CTRL, Ctrl); +} + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbMmc.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbMmc.c new file mode 100644 index 000000000000..9f423bd91ab0 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbMmc.c @@ -0,0 +1,398 @@ +/** @file + MMC/eMMC Protocol Functions (ported from Depthcharge mmc.c) + + Copyright (c) 2025, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +/** + Initialize eMMC device and read parameters. + + @param[in] Device Device context + + @retval EFI_SUCCESS eMMC initialized successfully + @retval other Initialization failed +**/ +EFI_STATUS +MmcStartup ( + IN SD_MMC_CB_DEVICE *Device + ) +{ + EFI_STATUS Status; + UINT32 Response[4]; + UINT32 OcrValue; + UINT32 Retry; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: MmcStartup begin\n")); + + // + // On warm boot, clear any leftover timing modes (HS400/HS200/etc.) from previous session + // Reset HOST_CONTROL and HOST_CONTROL2 to default state + // + SdhciWriteb (Device, 0, SDHCI_HOST_CONTROL); + SdhciWritew (Device, 0, SDHCI_HOST_CONTROL2); + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Reset host control registers for warm boot\n")); + + // On warm boot, if GL9763E had Enhanced Strobe enabled, it must be disabled + if (Device->IsGL9763E) { + Gl9763eSetEnhancedStrobe (Device, FALSE); + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Disabled Enhanced Strobe for warm boot\n")); + } + + // + // CMD0: GO_IDLE_STATE + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD0\n")); + Status = SdhciSendCommand (Device, MMC_CMD_GO_IDLE_STATE, 0, MMC_RSP_NONE, NULL, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD0 failed: %r\n", Status)); + return Status; + } + + // 10ms delay after CMD0 - eMMC needs time to exit idle state + gBS->Stall (10000); + + // + // CMD1: SEND_OP_COND (with retry loop like Depthcharge) + // + OcrValue = 0x40FF8000; // High capacity, voltage range + Retry = 100; + + while (Retry > 0) { + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: Sending CMD1 (retry=%d)\n", Retry)); + Status = SdhciSendCommand (Device, MMC_CMD_SEND_OP_COND, OcrValue, MMC_RSP_R3, Response, NULL, 0, 0, FALSE); + + if (!EFI_ERROR (Status)) { + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: CMD1 response = 0x%08x\n", Response[0])); + + // + // Check if busy bit is clear (card ready) + // + if (Response[0] & OCR_BUSY) { + // + // Check for High Capacity Support (block addressing) + // + Device->HighCapacity = ((Response[0] & OCR_HCS) == OCR_HCS); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: eMMC ready! OCR=0x%08x, HighCapacity=%d\n", + Response[0], Device->HighCapacity)); + break; + } + } + + gBS->Stall (10000); // 10ms delay between retries + Retry--; + } + + if (Retry == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD1 never succeeded\n")); + return EFI_DEVICE_ERROR; + } + + // + // CMD2: ALL_SEND_CID + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD2\n")); + Status = SdhciSendCommand (Device, MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD2 failed: %r\n", Status)); + return Status; + } + + // Save CID for DiskInfo protocol + // Per SD Host Controller Simplified Spec 3.0 Table 2-12, CID is in Response[0-3] + // but we need to skip the first byte and copy 15 bytes for EMMC_CID structure + CopyMem (((UINT8 *)&Device->Cid.EmmcCid) + 1, &Response[0], sizeof (EMMC_CID) - 1); + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: CID = %08x %08x %08x %08x\n", + Response[0], Response[1], Response[2], Response[3])); + + // + // CMD3: SET_RELATIVE_ADDR + // + Device->RelativeCardAddress = 1; // Use RCA = 1 + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD3\n")); + Status = SdhciSendCommand (Device, MMC_CMD_SET_RELATIVE_ADDR, + Device->RelativeCardAddress << 16, MMC_RSP_R1, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD3 failed: %r\n", Status)); + return Status; + } + + // + // CMD7: SELECT_CARD - Put the card in transfer state + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD7 (SELECT_CARD)\n")); + Status = SdhciSendCommand (Device, MMC_CMD_SELECT_CARD, + Device->RelativeCardAddress << 16, MMC_RSP_R1, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD7 failed: %r\n", Status)); + return Status; + } + + // + // CMD16: SET_BLOCKLEN to 512 bytes + // + Device->BlockSize = 512; + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD16 (SET_BLOCKLEN to %d)\n", Device->BlockSize)); + Status = SdhciSendCommand (Device, MMC_CMD_SET_BLOCKLEN, + Device->BlockSize, MMC_RSP_R1, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD16 failed: %r\n", Status)); + return Status; + } + + // + // CMD8: SEND_EXT_CSD to get extended CSD register + // + UINT8 *ExtCsd; + ExtCsd = AllocatePool (EXT_CSD_SIZE); + if (ExtCsd == NULL) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to allocate EXT_CSD buffer\n")); + return EFI_OUT_OF_RESOURCES; + } + + Status = SdhciSendCommand (Device, MMC_CMD_SEND_EXT_CSD, 0, MMC_RSP_R1, Response, + ExtCsd, EXT_CSD_SIZE, 1, TRUE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD8 (SEND_EXT_CSD) failed: %r\n", Status)); + FreePool (ExtCsd); + return Status; + } + + // + // Get capacity from EXT_CSD + // + UINT32 SecCount = *(UINT32 *)&ExtCsd[EXT_CSD_SEC_CNT]; + Device->TotalBlocks = SecCount; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: EXT_CSD: REV=%d, CARD_TYPE=0x%02x, SEC_CNT=%d, STROBE=%d\n", + ExtCsd[EXT_CSD_REV], ExtCsd[EXT_CSD_CARD_TYPE], SecCount, ExtCsd[EXT_CSD_STROBE_SUPPORT])); + + // + // Switch to best supported speed mode + // Priority: HS400-ES > HS400 > HS200 > HS + // + UINT32 SwitchArg; + UINT8 HostControl; + BOOLEAN SupportsHS400 = (ExtCsd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_HS400_1_8V) != 0; + BOOLEAN SupportsHS200 = (ExtCsd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_HS200_1_8V) != 0; + BOOLEAN SupportsStrobe = (ExtCsd[EXT_CSD_STROBE_SUPPORT] != 0); + + if (SupportsHS400 || SupportsHS200) { + // + // Card supports HS200 - switch to it for maximum performance (200 MHz) + // + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switching to HS200 mode (200 MHz)...\n")); + + // + // On warm boot, wait for card to be not busy before attempting mode switches + // After CMD0 reset, DAT0 line might still be low (busy) + // + UINT32 Timeout = 100000; // 100ms timeout + UINT32 PresentState; + while (Timeout > 0) { + PresentState = SdhciReadl (Device, SDHCI_PRESENT_STATE); + if ((PresentState & SDHCI_DATA_INHIBIT) == 0) { + break; // DAT0 is high, card not busy + } + gBS->Stall (1000); // 1ms + Timeout -= 1000; + } + if (Timeout == 0) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Card still busy after reset, PresentState=0x%08x\n", PresentState)); + } + + // + // Reset card to legacy timing mode (warm boot: exits HS400/HS200 from previous session) + // + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_HS_TIMING << 16) | + (EXT_CSD_TIMING_LEGACY << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to reset to legacy timing: %r\n", Status)); + // Continue anyway, might work + } + gBS->Stall (1000); // 1ms for timing change to take effect + + // Step 1: Switch bus width to 8-bit + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_BUS_WIDTH << 16) | + (EXT_CSD_BUS_WIDTH_8 << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to switch to 8-bit: %r\n", Status)); + goto FallbackToHS; + } + + // Step 2: Disable clock (REQUIRED before timing changes per SDHCI spec) + SdhciWritew (Device, 0, SDHCI_CLOCK_CONTROL); + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Clock disabled for timing change\n")); + + // Set host controller to 8-bit mode + high speed + HostControl = SdhciReadb (Device, SDHCI_HOST_CONTROL); + HostControl |= SDHCI_CTRL_8BITBUS | SDHCI_CTRL_HISPD; + SdhciWriteb (Device, SDHCI_HOST_CONTROL, HostControl); + + // Configure HOST_CONTROL2 for HS200 (SDR104 timing @ 1.8V) + UINT16 HostControl2 = SdhciReadw (Device, SDHCI_HOST_CONTROL2); + HostControl2 &= ~SDHCI_CTRL_UHS_MASK; + HostControl2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; + HostControl2 |= SDHCI_CTRL_UHS_SDR104; // HS200 uses SDR104 timing + HostControl2 |= SDHCI_CTRL_DRV_TYPE_A; // Driver strength Type A (recommended for HS200) + HostControl2 |= SDHCI_CTRL_180V_SIGNALING_ENABLE; // Enable 1.8V signaling + SdhciWritew (Device, SDHCI_HOST_CONTROL2, HostControl2); + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: HOST_CONTROL2 configured for HS200\n")); + + // Step 3: Switch eMMC to HS200 timing + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_HS_TIMING << 16) | + (EXT_CSD_TIMING_HS200 << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to switch to HS200: %r\n", Status)); + goto FallbackToHS; + } + + // Step 4: Set clock to 200 MHz + Status = SdhciSetClock (Device, 200000000); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to set 200 MHz clock: %r\n", Status)); + goto FallbackToHS; + } + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switched to HS200 @ 200 MHz, 8-bit, 1.8V!\n")); + + // + // If card supports HS400, switch from HS200 to HS400 (or HS400-ES) for DDR performance + // HS400 tuning sequence: HS200 → HS → HS400 (or HS400-ES if strobe supported) + // + if (SupportsHS400) { + BOOLEAN UseEnhancedStrobe = SupportsStrobe && Device->IsGL9763E; // GL9763E supports ES + + if (UseEnhancedStrobe) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Upgrading to HS400-ES (DDR 200 MHz + Enhanced Strobe)...\n")); + } else { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Upgrading to HS400 (DDR 200 MHz)...\n")); + } + + // Step 1: Switch card back to HS timing at ≤52 MHz + SdhciWritew (Device, 0, SDHCI_CLOCK_CONTROL); // Disable clock + + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_HS_TIMING << 16) | + (EXT_CSD_TIMING_HS << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to switch to HS for HS400: %r\n", Status)); + // Stay at HS200 + goto HS200Complete; + } + + // Set clock to 52 MHz for HS + Status = SdhciSetClock (Device, 52000000); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to set 52 MHz clock: %r\n", Status)); + goto HS200Complete; + } + + // Step 2: Switch to 8-bit DDR bus width (with Enhanced Strobe if supported) + SdhciWritew (Device, 0, SDHCI_CLOCK_CONTROL); // Disable clock + + UINT8 BusWidthValue = EXT_CSD_DDR_BUS_WIDTH_8; + if (UseEnhancedStrobe) { + BusWidthValue |= EXT_CSD_BUS_WIDTH_STROBE; // Enable Enhanced Strobe + } + + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_BUS_WIDTH << 16) | + (BusWidthValue << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to switch to 8-bit DDR%s: %r\n", + UseEnhancedStrobe ? "+Strobe" : "", Status)); + goto HS200Complete; + } + + // Step 3: Configure HOST_CONTROL2 for HS400 + HostControl2 = SdhciReadw (Device, SDHCI_HOST_CONTROL2); + HostControl2 &= ~SDHCI_CTRL_UHS_MASK; + HostControl2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; + HostControl2 |= SDHCI_CTRL_HS400; // HS400 mode + HostControl2 |= SDHCI_CTRL_DRV_TYPE_A; + HostControl2 |= SDHCI_CTRL_180V_SIGNALING_ENABLE; + SdhciWritew (Device, SDHCI_HOST_CONTROL2, HostControl2); + + // Step 4: Switch card to HS400 timing + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_HS_TIMING << 16) | + (EXT_CSD_TIMING_HS400 << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to switch to HS400: %r\n", Status)); + goto HS200Complete; + } + + // Step 5: Set clock to 200 MHz (DDR = 400 MHz effective) + Status = SdhciSetClock (Device, 200000000); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to set 200 MHz for HS400: %r\n", Status)); + goto HS200Complete; + } + + // Step 6: Enable Enhanced Strobe in GL9763E register if using HS400-ES + if (UseEnhancedStrobe && Device->IsGL9763E) { + Gl9763eSetEnhancedStrobe (Device, TRUE); + } + + if (UseEnhancedStrobe) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switched to HS400-ES @ 200 MHz DDR (400 MHz effective + Strobe), 8-bit, 1.8V!\n")); + } else { + DEBUG ((DEBUG_INFO, "SdMmcPiCb: Switched to HS400 @ 200 MHz DDR (400 MHz effective), 8-bit, 1.8V!\n")); + } + } +HS200Complete: + ; // Empty statement for label + } else { +FallbackToHS: + // + // Fallback to HS mode (52 MHz) + // + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switching to HS mode (52 MHz)...\n")); + + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_HS_TIMING << 16) | + (EXT_CSD_TIMING_HS << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (!EFI_ERROR (Status)) { + // Switch bus width to 8-bit + SwitchArg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_BUS_WIDTH << 16) | + (EXT_CSD_BUS_WIDTH_8 << 8); + Status = SdhciSendCommand (Device, MMC_CMD_SWITCH, SwitchArg, MMC_RSP_R1B, Response, NULL, 0, 0, FALSE); + if (!EFI_ERROR (Status)) { + HostControl = SdhciReadb (Device, SDHCI_HOST_CONTROL); + HostControl |= SDHCI_CTRL_8BITBUS | SDHCI_CTRL_HISPD; + SdhciWriteb (Device, SDHCI_HOST_CONTROL, HostControl); + } + + // Set clock to 52 MHz + Status = SdhciSetClock (Device, 52000000); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switched to HS mode @ 52 MHz, 8-bit!\n")); + } + } + } + + FreePool (ExtCsd); + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: eMMC initialization complete!\n")); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: RCA = %d\n", Device->RelativeCardAddress)); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Block size = %d bytes\n", Device->BlockSize)); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Total blocks = %ld\n", Device->TotalBlocks)); + + return EFI_SUCCESS; +} + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbSd.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbSd.c new file mode 100644 index 000000000000..7efc1df838c1 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbSd.c @@ -0,0 +1,499 @@ +/** @file + SD card initialization routines for Depthcharge-based SD/MMC driver. + + Copyright (c) 2024, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +/** + Send SD application command (ACMD). + This is a helper that sends CMD55 followed by the actual ACMD. + + @param[in] Device Device context + @param[in] Acmd Application command index + @param[in] Arg Command argument + @param[in] ResponseType Expected response type + @param[out] Response Response buffer + + @retval EFI_SUCCESS Command succeeded + @retval Others Command failed +**/ +STATIC +EFI_STATUS +SdSendAppCmd ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT32 Acmd, + IN UINT32 Arg, + IN UINT32 ResponseType, + OUT UINT32 *Response + ) +{ + EFI_STATUS Status; + UINT32 Rca; + + // First send CMD55 (APP_CMD) with RCA + Rca = Device->RelativeCardAddress << 16; + Status = SdhciSendCommand (Device, SD_CMD_APP_CMD, Rca, MMC_RSP_R1, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD55 failed: %r\n", Status)); + return Status; + } + + // Then send the actual application command + Status = SdhciSendCommand (Device, Acmd, Arg, ResponseType, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: ACMD%d failed: %r\n", Acmd, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +/** + Initialize SD card. + + Based on SD Physical Layer Simplified Specification and Depthcharge's sd.c + + @param[in] Device Device context + + @retval EFI_SUCCESS SD card initialized successfully + @retval EFI_DEVICE_ERROR SD card initialization failed + @retval EFI_NOT_FOUND No SD card present +**/ +EFI_STATUS +SdStartup ( + IN SD_MMC_CB_DEVICE *Device + ) +{ + EFI_STATUS Status; + UINT32 Response[4]; + UINT32 Ocr; + UINT32 Retry; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: SdStartup begin\n")); + + // + // Check if card is present (for removable SD cards) + // + UINT32 PresentState = SdhciReadl (Device, SDHCI_PRESENT_STATE); + if (!(PresentState & SDHCI_CARD_PRESENT)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: No SD card present (PRESENT_STATE=0x%08x)\n", PresentState)); + return EFI_NOT_FOUND; + } + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Card present detected\n")); + + // + // CMD0: GO_IDLE_STATE + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD0 (GO_IDLE_STATE)\n")); + Status = SdhciSendCommand (Device, MMC_CMD_GO_IDLE_STATE, 0, 0, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD0 failed: %r\n", Status)); + return Status; + } + + // + // CMD8: SEND_IF_COND (check if card supports 2.7-3.6V and SD 2.0+) + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD8 (SEND_IF_COND)\n")); + Status = SdhciSendCommand ( + Device, + SD_CMD_SEND_IF_COND, + SD_CMD8_VHS_27_36 | SD_CMD8_CHECK_PATTERN, + MMC_RSP_R7, + Response, + NULL, 0, 0, FALSE + ); + + if (EFI_ERROR (Status)) { + // Card doesn't support CMD8 - might be SD 1.x + DEBUG ((DEBUG_WARN, "SdMmcPciCb: CMD8 not supported - SD 1.x card?\n")); + // Continue anyway - we'll try ACMD41 without HCS bit + } else { + // Check echo-back pattern + if ((Response[0] & 0xFF) != SD_CMD8_CHECK_PATTERN) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD8 pattern mismatch: 0x%02x\n", Response[0] & 0xFF)); + return EFI_DEVICE_ERROR; + } + DEBUG ((DEBUG_INFO, "SdMmcPciCb: SD 2.0+ card detected\n")); + } + + // + // ACMD41: SD_SEND_OP_COND - Poll until card is ready + // + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Polling ACMD41 (SD_SEND_OP_COND)\n")); + + // Note: For ACMD41 during initialization, RCA is 0 + Device->RelativeCardAddress = 0; + + Retry = 100; + while (Retry > 0) { + // Send ACMD41 with HCS (High Capacity Support), S18R (1.8V request), and voltage range + UINT32 Arg = SD_OCR_HCS | SD_OCR_S18R | SD_OCR_VDD_32_33 | 0x00FF8000; // 2.7-3.6V range + 1.8V switching + + Status = SdSendAppCmd (Device, SD_ACMD_SEND_OP_COND, Arg, MMC_RSP_R3, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: ACMD41 failed: %r\n", Status)); + return Status; + } + + Ocr = Response[0]; + + // Check if card is ready (busy bit clear) + if (Ocr & OCR_BUSY) { + break; + } + + gBS->Stall (10000); // 10ms delay + Retry--; + } + + if (Retry == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: ACMD41 timeout - card not ready\n")); + return EFI_DEVICE_ERROR; + } + + // Check if High Capacity + Device->HighCapacity = (Ocr & OCR_HCS) != 0; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: SD card ready! OCR=0x%08x, HighCapacity=%d\n", + Ocr, Device->HighCapacity)); + + // + // Perform voltage switch to 1.8V if supported (UHS-I requirement) + // Must be done early, before CMD2/CMD3 + // + BOOLEAN CardSupports1_8V = (Ocr & SD_OCR_S18R) != 0; + UINT32 Caps1 = SdhciReadl (Device, SDHCI_CAPABILITIES_1); + BOOLEAN ControllerSupportsUHS = ((Caps1 & (SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_DDR50)) != 0); + + if (CardSupports1_8V && ControllerSupportsUHS) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Attempting voltage switch to 1.8V for UHS-I...\n")); + + // Send CMD11 + Status = SdhciSendCommand (Device, SD_VOLTAGE_SWITCH, 0, MMC_RSP_R1, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: CMD11 failed: %r, continuing without UHS\n", Status)); + } else { + // Stop SD clock + SdhciWritew (Device, 0, SDHCI_CLOCK_CONTROL); + gBS->Stall (5000); // 5ms + + // Check DAT[3:0] lines should be 0 + UINT32 PresentState = SdhciReadl (Device, SDHCI_PRESENT_STATE); + if (((PresentState >> 20) & 0xF) != 0) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Voltage switch failed - DAT lines not 0 (PresentState=0x%08x)\n", PresentState)); + } else { + // Set 1.8V signaling enable bit + UINT16 HostControl2 = SdhciReadw (Device, SDHCI_HOST_CONTROL2); + HostControl2 |= SDHCI_CTRL_180V_SIGNALING_ENABLE; + SdhciWritew (Device, SDHCI_HOST_CONTROL2, HostControl2); + gBS->Stall (5000); // 5ms + + // Verify bit is set + HostControl2 = SdhciReadw (Device, SDHCI_HOST_CONTROL2); + if (!(HostControl2 & SDHCI_CTRL_180V_SIGNALING_ENABLE)) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: 1.8V signaling bit not set\n")); + } else { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Voltage switched to 1.8V successfully\n")); + } + } + + // Restart SD clock + SdhciSetClock (Device, 400000); // Restart at 400 KHz + gBS->Stall (1000); // 1ms + } + } + + // + // CMD2: ALL_SEND_CID + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD2 (ALL_SEND_CID)\n")); + Status = SdhciSendCommand (Device, MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD2 failed: %r\n", Status)); + return Status; + } + + // Save CID for DiskInfo protocol (SD format, not eMMC format) + CopyMem (((UINT8 *)&Device->Cid.SdCid) + 1, &Response[0], sizeof (SD_CID) - 1); + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: CID = %08x %08x %08x %08x\n", + Response[0], Response[1], Response[2], Response[3])); + + // + // CMD3: SEND_RELATIVE_ADDR (SD card selects its own RCA) + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD3 (SEND_RELATIVE_ADDR)\n")); + Status = SdhciSendCommand (Device, MMC_CMD_SET_RELATIVE_ADDR, 0, MMC_RSP_R6, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD3 failed: %r\n", Status)); + return Status; + } + + // Extract RCA from response (upper 16 bits) + Device->RelativeCardAddress = Response[0] >> 16; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: RCA = 0x%04x\n", Device->RelativeCardAddress)); + + // + // CMD9: SEND_CSD - Get Card Specific Data + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD9 (SEND_CSD)\n")); + Status = SdhciSendCommand ( + Device, + SD_CMD_SEND_CSD, + Device->RelativeCardAddress << 16, + MMC_RSP_R2, + Response, + NULL, 0, 0, FALSE + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD9 failed: %r\n", Status)); + return Status; + } + + // Parse CSD to get capacity + // Extract CSD_STRUCTURE from bits [127:126] (first 2 bits of Response[0]) + UINT8 CsdStructure = (Response[0] >> 30) & 0x03; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: CSD Response = %08x %08x %08x %08x\n", + Response[0], Response[1], Response[2], Response[3])); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: CSD_STRUCTURE = %d\n", CsdStructure)); + + if (CsdStructure == 0) { + // CSD Version 1.0 (SDSC): C_SIZE at bits [73:62], C_SIZE_MULT at bits [49:47], READ_BL_LEN at bits [83:80] + UINT32 ReadBlLen = (Response[1] >> 16) & 0x0F; // bits [83:80] + UINT32 CSize = ((Response[1] & 0x03FF) << 2) | ((Response[2] >> 30) & 0x03); // bits [73:62] + UINT32 CMult = (Response[2] >> 15) & 0x07; // bits [49:47] + + Device->TotalBlocks = (CSize + 1) * (1 << (CMult + 2)) * (1 << ReadBlLen) / 512; + } else if (CsdStructure == 1) { + // CSD Version 2.0 (SDHC/SDXC): C_SIZE at bits [69:48] + UINT32 CSize = ((Response[1] & 0x3F) << 16) | (Response[2] >> 16); // bits [69:48] + Device->TotalBlocks = (CSize + 1) * 1024; // In 512-byte blocks + } else { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Unknown CSD structure version: %d\n", CsdStructure)); + return EFI_DEVICE_ERROR; + } + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: SD capacity: %lld blocks (CSD v%d)\n", + Device->TotalBlocks, CsdStructure)); + + // + // CMD7: SELECT_CARD + // + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD7 (SELECT_CARD)\n")); + Status = SdhciSendCommand ( + Device, + MMC_CMD_SELECT_CARD, + Device->RelativeCardAddress << 16, + MMC_RSP_R1B, + Response, + NULL, 0, 0, FALSE + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD7 failed: %r\n", Status)); + return Status; + } + + // + // Set block size to 512 bytes + // + Device->BlockSize = 512; + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Sending CMD16 (SET_BLOCKLEN to 512)\n")); + Status = SdhciSendCommand (Device, MMC_CMD_SET_BLOCKLEN, 512, MMC_RSP_R1, Response, NULL, 0, 0, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD16 failed: %r\n", Status)); + return Status; + } + + // + // Switch to 4-bit bus width using ACMD6 + // + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switching to 4-bit bus width\n")); + Status = SdSendAppCmd (Device, SD_ACMD_SET_BUS_WIDTH, 2, MMC_RSP_R1, Response); // 2 = 4-bit + if (!EFI_ERROR (Status)) { + // Set controller to 4-bit mode + UINT8 HostControl = SdhciReadb (Device, SDHCI_HOST_CONTROL); + HostControl |= SDHCI_CTRL_4BITBUS; + SdhciWriteb (Device, SDHCI_HOST_CONTROL, HostControl); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switched to 4-bit bus width\n")); + } + + // + // Switch to High Speed mode (50 MHz) if supported + // Read Switch Function status to check HS support + // Note: Must be DMA-aligned for ADMA transfers + // + UINT8 *SwitchStatus = AllocateAlignedPages (EFI_SIZE_TO_PAGES (64), 512); + if (SwitchStatus == NULL) { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to allocate SwitchStatus buffer\n")); + Status = SdhciSetClock (Device, 25000000); + goto SkipHighSpeed; + } + + // CMD6: SWITCH_FUNC - Check if High Speed is supported (Mode 0 = check) + Status = SdhciSendCommand ( + Device, + MMC_CMD_SWITCH, + 0x00FFFF01, // Mode=0 (check), Group1=1 (HS), keep others at 0xF + MMC_RSP_R1, + Response, + SwitchStatus, + 64, + 1, + TRUE + ); + + if (!EFI_ERROR (Status)) { + // Check if High Speed is supported (bits 401-415 in switch status) + if (SwitchStatus[13] & 0x02) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: High Speed supported, switching...\n")); + + // CMD6: SWITCH_FUNC - Switch to High Speed (Mode 1 = switch) + Status = SdhciSendCommand ( + Device, + MMC_CMD_SWITCH, + 0x80FFFF01, // Mode=1 (switch), Group1=1 (HS) + MMC_RSP_R1, + Response, + SwitchStatus, + 64, + 1, + TRUE + ); + + if (!EFI_ERROR (Status)) { + // Disable clock before changing timing (required by SDHCI spec) + SdhciWritew (Device, 0, SDHCI_CLOCK_CONTROL); + + // Set HISPD bit in HOST_CONTROL + UINT8 HostControl = SdhciReadb (Device, SDHCI_HOST_CONTROL); + HostControl |= SDHCI_CTRL_HISPD; + SdhciWriteb (Device, SDHCI_HOST_CONTROL, HostControl); + + // Increase clock to 50 MHz + Status = SdhciSetClock (Device, 50000000); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switched to High Speed @ 50 MHz!\n")); + } + + // + // Try to upgrade to UHS-I modes if 1.8V signaling is enabled + // + UINT16 HostControl2 = SdhciReadw (Device, SDHCI_HOST_CONTROL2); + if (HostControl2 & SDHCI_CTRL_180V_SIGNALING_ENABLE) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: 1.8V signaling enabled, attempting UHS-I mode upgrade...\n")); + + // Try SDR104 first (fastest), then SDR50 + UINT8 TargetMode = 0; + UINT32 TargetClock = 0; + UINT16 UhsMode = 0; + CONST CHAR8 *ModeName = NULL; + + // Check card capabilities via CMD6 mode 0 (check) + Status = SdhciSendCommand ( + Device, + MMC_CMD_SWITCH, + 0x00FFFF01, // Mode=0 (check), Group1=0xF (query all) + MMC_RSP_R1, + Response, + SwitchStatus, + 64, + 1, + TRUE + ); + + if (!EFI_ERROR (Status)) { + // Check which UHS modes are supported (byte 13, bits 400-407) + // Bit 403=SDR104, 402=SDR50, 401=HS (already set), 400=Default + UINT8 SupportedModes = SwitchStatus[13]; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Card supported modes = 0x%02x\n", SupportedModes)); + + // Try SDR104 @ 208 MHz (bit 3) + if (SupportedModes & 0x08) { + TargetMode = 3; // SDR104 + TargetClock = 208000000; + UhsMode = SDHCI_CTRL_UHS_SDR104; + ModeName = "SDR104"; + } + // Try SDR50 @ 100 MHz (bit 2) + else if (SupportedModes & 0x04) { + TargetMode = 2; // SDR50 + TargetClock = 100000000; + UhsMode = SDHCI_CTRL_UHS_SDR50; + ModeName = "SDR50"; + } + + if (TargetMode != 0) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Attempting to switch to %a...\n", ModeName)); + + // CMD6 mode 1 (switch) to target mode + UINT32 SwitchArg = 0x80FFFF00 | TargetMode; // Mode=1 (switch), Group1=target + Status = SdhciSendCommand ( + Device, + MMC_CMD_SWITCH, + SwitchArg, + MMC_RSP_R1, + Response, + SwitchStatus, + 64, + 1, + TRUE + ); + + if (!EFI_ERROR (Status)) { + // Stop clock before changing timing + SdhciWritew (Device, 0, SDHCI_CLOCK_CONTROL); + + // Set UHS mode in HOST_CONTROL2 + HostControl2 = SdhciReadw (Device, SDHCI_HOST_CONTROL2); + HostControl2 &= ~SDHCI_CTRL_UHS_MASK; + HostControl2 |= UhsMode; + SdhciWritew (Device, SDHCI_HOST_CONTROL2, HostControl2); + + // Set the target clock frequency + Status = SdhciSetClock (Device, TargetClock); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Switched to UHS-I %a @ %d MHz!\n", + ModeName, TargetClock / 1000000)); + } else { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Failed to set %d MHz clock\n", TargetClock / 1000000)); + } + } else { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: CMD6 switch to %a failed: %r\n", ModeName, Status)); + } + } else { + DEBUG ((DEBUG_INFO, "SdMmcPciCb: No UHS-I modes supported by card, staying at HS\n")); + } + } else { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: CMD6 check for UHS modes failed: %r\n", Status)); + } + } + } // Close if (!EFI_ERROR (Status)) from CMD6 mode 1 for HS + } // Close if (SwitchStatus[13] & 0x02) - HS supported check + else { // HS not supported + DEBUG ((DEBUG_INFO, "SdMmcPciCb: High Speed not supported, staying at 25 MHz\n")); + Status = SdhciSetClock (Device, 25000000); + } + } // Close if (!EFI_ERROR (Status)) from line 304 (CMD6 mode 0 for HS) + else { + // CMD6 failed, stay at default speed + DEBUG ((DEBUG_WARN, "SdMmcPciCb: CMD6 failed, staying at default speed\n")); + Status = SdhciSetClock (Device, 25000000); + } + + // Free the aligned buffer + FreeAlignedPages (SwitchStatus, EFI_SIZE_TO_PAGES (64)); + +SkipHighSpeed: + DEBUG ((DEBUG_INFO, "SdMmcPciCb: SD card initialization complete!\n")); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: RCA = 0x%04x\n", Device->RelativeCardAddress)); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Block size = %d bytes\n", Device->BlockSize)); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Total blocks = %lld\n", Device->TotalBlocks)); + + return EFI_SUCCESS; +} + diff --git a/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbSdhci.c b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbSdhci.c new file mode 100644 index 000000000000..ea96338129e9 --- /dev/null +++ b/UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbSdhci.c @@ -0,0 +1,695 @@ +/** @file + SDHCI Core Functions (ported from Depthcharge sdhci.c) + + Copyright (c) 2025, Matt DeVillier. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SdMmcPciCbDxe.h" + +/** + Reset the SDHCI controller. + + @param[in] Device Device context + @param[in] Mask Reset mask (SDHCI_RESET_ALL, SDHCI_RESET_CMD, SDHCI_RESET_DATA) + + @retval EFI_SUCCESS Reset successful + @retval other Reset failed +**/ +EFI_STATUS +SdhciReset ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT8 Mask + ) +{ + UINT32 Timeout; + UINT8 Value; + + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: SdhciReset(0x%02x)\n", Mask)); + + // + // Write reset mask + // + SdhciWriteb (Device, SDHCI_SOFTWARE_RESET, Mask); + + // + // Wait for reset to complete (max 100ms) + // + Timeout = 100000; // 100ms in microseconds + while (Timeout > 0) { + Value = SdhciReadb (Device, SDHCI_SOFTWARE_RESET); + if ((Value & Mask) == 0) { + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Reset complete\n")); + return EFI_SUCCESS; + } + gBS->Stall (10); + Timeout -= 10; + } + + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Reset timeout!\n")); + return EFI_TIMEOUT; +} + +/** + Set power mode and voltage. + + @param[in] Device Device context + @param[in] PowerMode Power mode (SDHCI_POWER_330, etc.) + + @retval EFI_SUCCESS Power set successfully +**/ +EFI_STATUS +SdhciSetPower ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT8 PowerMode + ) +{ + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: SdhciSetPower(0x%02x)\n", PowerMode)); + + // + // Set voltage and power on + // + SdhciWriteb (Device, SDHCI_POWER_CONTROL, PowerMode | SDHCI_POWER_ON); + + // + // Wait 10ms for power to stabilize + // + gBS->Stall (10000); + + return EFI_SUCCESS; +} + +/** + Set clock frequency. + + @param[in] Device Device context + @param[in] Clock Desired clock frequency in Hz + + @retval EFI_SUCCESS Clock set successfully +**/ +EFI_STATUS +SdhciSetClock ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT32 Clock + ) +{ + UINT32 Div; + UINT16 ClkReg; + UINT32 Timeout; + + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: SdhciSetClock(%d Hz)\n", Clock)); + + // + // Disable clock first + // + SdhciWritew (Device, SDHCI_CLOCK_CONTROL, 0); + + if (Clock == 0) { + return EFI_SUCCESS; + } + + // + // Calculate divisor (SDHCI 3.0 spec: Actual Clock = Base Clock / (2 * Div)) + // Div = 0 means no division (full speed) + // + Div = 0; + UINT32 ActualClock = Clock; + if (Device->ClockBase > 0) { + for (Div = 1; Div < 256; Div++) { + if ((Device->ClockBase / (2 * Div)) <= Clock) { + break; + } + } + if (Div == 256) { + Div = 255; + } + Div >>= 1; + + // Calculate actual clock + if (Div == 0) { + ActualClock = Device->ClockBase; + } else { + ActualClock = Device->ClockBase / (2 * Div); + } + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Clock: requested=%u, divider=%u, actual=%u Hz\n", + Clock, Div, ActualClock)); + } + + // + // Set divisor and enable internal clock + // + ClkReg = (Div << SDHCI_DIVIDER_SHIFT) | SDHCI_CLOCK_INT_EN; + SdhciWritew (Device, SDHCI_CLOCK_CONTROL, ClkReg); + + // + // Wait for internal clock to stabilize + // + Timeout = 20000; // 20ms + while (Timeout > 0) { + if (SdhciReadw (Device, SDHCI_CLOCK_CONTROL) & SDHCI_CLOCK_INT_STABLE) { + break; + } + gBS->Stall (10); + Timeout -= 10; + } + + if (Timeout == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Internal clock never stabilized\n")); + return EFI_TIMEOUT; + } + + // + // Enable SD clock + // + ClkReg |= SDHCI_CLOCK_CARD_EN; + SdhciWritew (Device, SDHCI_CLOCK_CONTROL, ClkReg); + + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: Clock enabled\n")); + + return EFI_SUCCESS; +} + +/** + Send command (using Depthcharge's simple polling approach). + + @param[in] Device Device context + @param[in] Cmd Command index + @param[in] Arg Command argument + @param[in] ResponseType Expected response type (MMC_RSP_*) + @param[out] Response Response buffer (4 x UINT32) + @param[in] DataBuffer Optional data buffer for read/write + @param[in] BlockSize Block size for data transfer + @param[in] BlockCount Number of blocks to transfer + @param[in] IsRead TRUE for read, FALSE for write + + @retval EFI_SUCCESS Command successful + @retval other Command failed +**/ +EFI_STATUS +SdhciSendCommand ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT32 Cmd, + IN UINT32 Arg, + IN UINT32 ResponseType, + OUT UINT32 *Response, + IN VOID *DataBuffer OPTIONAL, + IN UINT32 BlockSize OPTIONAL, + IN UINT32 BlockCount OPTIONAL, + IN BOOLEAN IsRead OPTIONAL + ) +{ + EFI_STATUS Status; + UINT32 PresentState; + UINT32 Timeout; + UINT32 IntStatus; + UINT16 CmdReg; + UINT16 TransferMode; + UINT8 Flags; + + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: SdhciSendCommand CMD%d arg=0x%08x%s\n", + // Cmd, Arg, (DataBuffer != NULL) ? " [WITH DATA]" : "")); + + // + // Wait for CMD line ready + // For data commands, only wait for CMD_INHIBIT (not DATA_INHIBIT) + // + Timeout = 10000; + UINT32 InhibitMask = SDHCI_CMD_INHIBIT; + if (DataBuffer != NULL) { + InhibitMask |= SDHCI_DATA_INHIBIT; + } + + while (Timeout > 0) { + PresentState = SdhciReadl (Device, SDHCI_PRESENT_STATE); + if ((PresentState & InhibitMask) == 0) { + break; + } + gBS->Stall (10); + Timeout -= 10; + } + + if (Timeout == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD%d line not ready! PresentState=0x%08x (need 0x%08x clear)\n", + Cmd, PresentState, InhibitMask)); + return EFI_TIMEOUT; + } + + // + // Clear all status bits + // + SdhciWritel (Device, SDHCI_INT_STATUS, SDHCI_INT_ALL_MASK); + + // + // Set up data transfer if needed - Always use ADMA (like coreboot does) + // + if (DataBuffer != NULL && BlockSize > 0 && BlockCount > 0) { + // + // Set up ADMA descriptors + // + Status = SdhciSetupAdma (Device, DataBuffer, BlockSize * BlockCount, IsRead); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to setup ADMA: %r\n", Status)); + return Status; + } + + // + // Set block size and count + // + SdhciWritew (Device, SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(7, BlockSize)); + SdhciWritew (Device, SDHCI_BLOCK_COUNT, (UINT16)BlockCount); + + // + // Set transfer mode with DMA enabled + // + TransferMode = SDHCI_TRNS_DMA; + if (IsRead) { + TransferMode |= SDHCI_TRNS_READ; + } + if (BlockCount > 1) { + TransferMode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_ACMD12; + } + SdhciWritew (Device, SDHCI_TRANSFER_MODE, TransferMode); + } + + // + // Set argument + // + SdhciWritel (Device, SDHCI_ARGUMENT, Arg); + + // + // Build command register + // + Flags = 0; + if (DataBuffer != NULL) { + Flags |= SDHCI_CMD_DATA; + } + if (ResponseType & MMC_RSP_PRESENT) { + if (ResponseType & MMC_RSP_136) { + Flags |= SDHCI_CMD_RESP_LONG; // Fixed: OR instead of assign + } else if (ResponseType & MMC_RSP_BUSY) { + Flags |= SDHCI_CMD_RESP_SHORT_BUSY; // Fixed: OR instead of assign + } else { + Flags |= SDHCI_CMD_RESP_SHORT; // Fixed: OR instead of assign + } + } else { + Flags |= SDHCI_CMD_RESP_NONE; // Fixed: OR instead of assign (though 0) + } + + if (ResponseType & MMC_RSP_CRC) { + Flags |= SDHCI_CMD_CRC; + } + if (ResponseType & MMC_RSP_OPCODE) { + Flags |= SDHCI_CMD_INDEX; + } + + CmdReg = SDHCI_MAKE_CMD (Cmd, Flags); + + // + // Send command (debug output removed for performance) + // + SdhciWritew (Device, SDHCI_COMMAND, CmdReg); + + // + // Poll for command complete + // + Timeout = 100000; // 100ms + while (Timeout > 0) { + IntStatus = SdhciReadl (Device, SDHCI_INT_STATUS); + + if (IntStatus & SDHCI_INT_ERROR) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: CMD%d error! IntStatus=0x%08x (", Cmd, IntStatus)); + if (IntStatus & SDHCI_INT_TIMEOUT) DEBUG ((DEBUG_ERROR, "TIMEOUT ")); + if (IntStatus & SDHCI_INT_CRC) DEBUG ((DEBUG_ERROR, "CRC ")); + if (IntStatus & SDHCI_INT_END_BIT) DEBUG ((DEBUG_ERROR, "ENDBIT ")); + if (IntStatus & SDHCI_INT_INDEX) DEBUG ((DEBUG_ERROR, "INDEX ")); + if (IntStatus & SDHCI_INT_DATA_TIMEOUT) DEBUG ((DEBUG_ERROR, "DATA_TIMEOUT ")); + if (IntStatus & SDHCI_INT_DATA_CRC) DEBUG ((DEBUG_ERROR, "DATA_CRC ")); + if (IntStatus & SDHCI_INT_DATA_END_BIT) DEBUG ((DEBUG_ERROR, "DATA_ENDBIT ")); + if (IntStatus & SDHCI_INT_ADMA_ERROR) DEBUG ((DEBUG_ERROR, "ADMA_ERROR ")); + DEBUG ((DEBUG_ERROR, ")\n")); + SdhciWritel (Device, SDHCI_INT_STATUS, SDHCI_INT_ALL_MASK); + return EFI_DEVICE_ERROR; + } + + if (IntStatus & SDHCI_INT_RESPONSE) { + // + // Command complete! + // + SdhciWritel (Device, SDHCI_INT_STATUS, SDHCI_INT_RESPONSE); + + // + // Read response if needed + // + if (Response != NULL && (ResponseType & MMC_RSP_PRESENT)) { + if (ResponseType & MMC_RSP_136) { + // Long response (R2) - CRC is stripped so we need to do some shifting + // Read in reverse order and shift by 8 bits (like Depthcharge does) + Response[0] = SdhciReadl (Device, SDHCI_RESPONSE + 12) << 8; + Response[1] = SdhciReadl (Device, SDHCI_RESPONSE + 8) << 8; + Response[2] = SdhciReadl (Device, SDHCI_RESPONSE + 4) << 8; + Response[3] = SdhciReadl (Device, SDHCI_RESPONSE + 0) << 8; + // OR in the last byte from the previous register + Response[0] |= (SdhciReadl (Device, SDHCI_RESPONSE + 8) >> 24) & 0xFF; + Response[1] |= (SdhciReadl (Device, SDHCI_RESPONSE + 4) >> 24) & 0xFF; + Response[2] |= (SdhciReadl (Device, SDHCI_RESPONSE + 0) >> 24) & 0xFF; + } else { + // Short response + Response[0] = SdhciReadl (Device, SDHCI_RESPONSE); + } + } + + // DEBUG ((DEBUG_INFO, "SdMmcPciCb: CMD%d complete!\n", Cmd)); + + // + // If no data transfer, we're done + // + if (DataBuffer == NULL) { + return EFI_SUCCESS; + } + + // + // ADMA Data Transfer - controller handles everything + // + return SdhciCompleteAdma (Device, 10000); + } + + gBS->Stall (10); + Timeout -= 10; + } + + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Command timeout!\n")); + return EFI_TIMEOUT; +} + +/** + Initialize SDHCI controller. + + @param[in] Device Device context + + @retval EFI_SUCCESS Initialization successful +**/ +/** + Setup ADMA descriptor table for data transfer (from Depthcharge) + + @param[in] Device Pointer to device context + @param[in] DataBuffer Data buffer address + @param[in] TotalBytes Total bytes to transfer + @param[in] IsRead TRUE for read, FALSE for write + + @retval EFI_SUCCESS ADMA descriptors set up successfully + @retval Others Error occurred +**/ +EFI_STATUS +SdhciSetupAdma ( + IN SD_MMC_CB_DEVICE *Device, + IN VOID *DataBuffer, + IN UINT32 TotalBytes, + IN BOOLEAN IsRead + ) +{ + UINT32 NeedDescriptors; + UINT32 Remaining; + UINT32 i; + UINT8 *BufferPtr; + UINT16 Attributes; + UINT32 DescLength; + EFI_PHYSICAL_ADDRESS DescTableAddr; + + if (TotalBytes == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: SdhciSetupAdma: Invalid TotalBytes=0\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Calculate how many descriptors we need + // + NeedDescriptors = 1 + (TotalBytes / SDHCI_MAX_PER_DESCRIPTOR); + + // + // Allocate or reallocate descriptor table if needed + // + if (Device->AdmaDescs == NULL || Device->AdmaDescCount < NeedDescriptors) { + if (Device->AdmaDescs != NULL) { + FreePool (Device->AdmaDescs); + Device->AdmaDescs = NULL; + Device->AdmaDescCount = 0; + } + + Device->AdmaDescs = AllocatePool (NeedDescriptors * sizeof (SDHCI_ADMA_DESC)); + if (Device->AdmaDescs == NULL) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: Failed to allocate ADMA descriptors\n")); + return EFI_OUT_OF_RESOURCES; + } + Device->AdmaDescCount = NeedDescriptors; + } + + // + // Build descriptor chain using direct physical addresses + // + BufferPtr = (UINT8 *)DataBuffer; + Remaining = TotalBytes; + + for (i = 0; Remaining > 0; i++) { + if (Remaining < SDHCI_MAX_PER_DESCRIPTOR) { + DescLength = Remaining; + } else { + DescLength = SDHCI_MAX_PER_DESCRIPTOR; + } + Remaining -= DescLength; + + Attributes = SDHCI_ADMA_VALID | SDHCI_ACT_TRAN; + if (Remaining == 0) { + Attributes |= SDHCI_ADMA_END; + } + + Device->AdmaDescs[i].Attributes = Attributes; + Device->AdmaDescs[i].Length = (UINT16)(DescLength & 0xFFFF); + Device->AdmaDescs[i].Address = (UINT32)(UINTN)BufferPtr; + + BufferPtr += DescLength; + } + + // + // Write descriptor table address to ADMA registers + // + DescTableAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Device->AdmaDescs; + SdhciWritel (Device, SDHCI_ADMA_ADDRESS, (UINT32)DescTableAddr); + if (Device->UseDma64) { + SdhciWritel (Device, SDHCI_ADMA_ADDRESS_HI, (UINT32)(DescTableAddr >> 32)); + } + + DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: ADMA setup: %d descriptors, %d bytes\n", + NeedDescriptors, TotalBytes)); + + return EFI_SUCCESS; +} + +/** + Wait for ADMA transfer to complete (from Depthcharge) + + @param[in] Device Pointer to device context + @param[in] TimeoutMs Timeout in milliseconds + + @retval EFI_SUCCESS Transfer completed successfully + @retval EFI_TIMEOUT Transfer timed out + @retval Others Error occurred +**/ +EFI_STATUS +SdhciCompleteAdma ( + IN SD_MMC_CB_DEVICE *Device, + IN UINT32 TimeoutMs + ) +{ + UINT32 IntStatus; + UINT32 Mask; + UINT32 Retry; + + // + // Wait for command response or data end + // (On some controllers, DATA_END may arrive before RESPONSE for fast transfers) + // + Mask = SDHCI_INT_RESPONSE | SDHCI_INT_DATA_END | SDHCI_INT_ERROR; + Retry = 10000; // 10ms timeout for command + + while (Retry > 0) { + IntStatus = SdhciReadl (Device, SDHCI_INT_STATUS); + if ((IntStatus & Mask) != 0) { + break; + } + gBS->Stall (1); // 1 microsecond delay + Retry--; + } + + if (Retry == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: ADMA command timeout! IntStatus=0x%08x\n", IntStatus)); + SdhciReset (Device, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + return EFI_TIMEOUT; + } + + // Check for errors first + if ((IntStatus & SDHCI_INT_ERROR) != 0) { + UINT32 AdmaError = SdhciReadl (Device, SDHCI_ADMA_ERROR); + UINT32 AdmaAddr = SdhciReadl (Device, SDHCI_ADMA_ADDRESS); + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: ADMA command error: IntStatus=0x%08x, AdmaError=0x%08x, AdmaAddr=0x%08x\n", + IntStatus, AdmaError, AdmaAddr)); + + // Reset controller + SdhciReset (Device, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + return EFI_DEVICE_ERROR; + } + + // If we got DATA_END already, transfer is complete! + if ((IntStatus & SDHCI_INT_DATA_END) != 0) { + // DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: ADMA transfer complete (fast path)\n")); + SdhciWritel (Device, SDHCI_INT_STATUS, SDHCI_INT_ALL_MASK); + return EFI_SUCCESS; + } + + // Otherwise, clear command response and wait for data + SdhciWritel (Device, SDHCI_INT_STATUS, SDHCI_INT_RESPONSE); + // DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: ADMA command response received, waiting for data...\n")); + + // + // Now wait for data transfer to complete + // + Mask = SDHCI_INT_DATA_END | SDHCI_INT_ERROR | SDHCI_INT_ADMA_ERROR; + Retry = TimeoutMs * 1000; // Convert to microseconds + + while (Retry > 0) { + IntStatus = SdhciReadl (Device, SDHCI_INT_STATUS); + if ((IntStatus & Mask) != 0) { + break; + } + gBS->Stall (1); // 1 microsecond delay + Retry--; + } + + // Clear all status bits + SdhciWritel (Device, SDHCI_INT_STATUS, IntStatus); + + if (Retry == 0) { + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: ADMA data timeout\n")); + return EFI_TIMEOUT; + } + + if ((IntStatus & (SDHCI_INT_ERROR | SDHCI_INT_ADMA_ERROR)) != 0) { + UINT32 AdmaError = SdhciReadl (Device, SDHCI_ADMA_ERROR); + DEBUG ((DEBUG_ERROR, "SdMmcPciCb: ADMA transfer error: IntStatus=0x%08x, AdmaError=0x%08x\n", + IntStatus, AdmaError)); + + // Reset data line + SdhciReset (Device, SDHCI_RESET_DATA); + return EFI_DEVICE_ERROR; + } + + // DEBUG ((DEBUG_VERBOSE, "SdMmcPciCb: ADMA transfer complete\n")); + return EFI_SUCCESS; +} + +EFI_STATUS +SdhciInit ( + IN SD_MMC_CB_DEVICE *Device + ) +{ + EFI_STATUS Status; + UINT32 Caps; + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: SdhciInit start\n")); + + // + // Reset controller + // + Status = SdhciReset (Device, SDHCI_RESET_ALL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Power cycle to ensure clean state (important for warm boot) + // On warm boot, card may be in high-speed mode (HS400/HS200/SDR50) + // + SdhciWriteb (Device, 0, SDHCI_POWER_CONTROL); + gBS->Stall (10000); // 10ms + + // Set appropriate voltage (1.8V for eMMC, will be adjusted for SD if needed) + UINT8 PowerMode = SDHCI_POWER_ON; + if (Device->IsEMMC) { + PowerMode |= SDHCI_POWER_180; + } else { + PowerMode |= SDHCI_POWER_330; + } + SdhciWriteb (Device, PowerMode, SDHCI_POWER_CONTROL); + gBS->Stall (10000); // 10ms for power to stabilize + + // + // Read capabilities to determine clock base and ADMA support + // + Caps = SdhciReadl (Device, SDHCI_CAPABILITIES); + Device->ClockBase = ((Caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT) * 1000000; + + if (Device->ClockBase == 0) { + // Fallback for older controllers + Device->ClockBase = ((Caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT) * 1000000; + } + + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Clock base = %d Hz\n", Device->ClockBase)); + + // + // Check for ADMA support and enable it + // Force ADMA32 mode for compatibility (ADMA64 only needed for buffers >4GB) + // + if ((Caps & SDHCI_CAN_DO_ADMA2) != 0) { + UINT8 HostControl; + + Device->UseDma64 = FALSE; // Force ADMA32 for now + + HostControl = SdhciReadb (Device, SDHCI_HOST_CONTROL); + HostControl &= ~SDHCI_CTRL_DMA_MASK; + HostControl |= SDHCI_CTRL_ADMA32; + SdhciWriteb (Device, SDHCI_HOST_CONTROL, HostControl); + DEBUG ((DEBUG_INFO, "SdMmcPciCb: Enabling ADMA32 mode\n")); + } else { + DEBUG ((DEBUG_WARN, "SdMmcPciCb: Controller doesn't support ADMA!\n")); + } + + // + // Set power to 3.3V + // + Status = SdhciSetPower (Device, SDHCI_POWER_330); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Enable interrupts - Match Depthcharge EXACTLY + // Enable only data and command interrupts for status polling + // + SdhciWritel (Device, SDHCI_INT_ENABLE, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK); + SdhciWritel (Device, SDHCI_SIGNAL_ENABLE, 0x0); // Depthcharge uses 0, not ALL_MASK! + + // + // Set initial clock to 400 KHz for identification + // + Status = SdhciSetClock (Device, 400000); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // GL9763E-specific initialization + // + if (Device->IsGL9763E) { + Status = Gl9763eInit (Device); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Device->Initialized = TRUE; + DEBUG ((DEBUG_INFO, "SdMmcPciCb: SdhciInit complete\n")); + + return EFI_SUCCESS; +} + diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/CfrSetupMenuDxe.inf b/UefiPayloadPkg/CfrSetupMenuDxe/CfrSetupMenuDxe.inf new file mode 100644 index 000000000000..ceaa96bee3d4 --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/CfrSetupMenuDxe.inf @@ -0,0 +1,59 @@ +## @file +# Implementation of a CFR consumer as a HII setup menu. +# +# Copyright (c) 2023, 9elements GmbH.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CfrSetupMenuDxe + FILE_GUID = F93C9BC1-D179-49B2-B5C0-94C15862A28D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = CfrSetupMenuEntryPoint + UNLOAD_IMAGE = CfrSetupMenuUnload + +[Sources] + SetupMenu.c + SetupMenuCfr.c + SetupMenuHii.c + SetupMenuVfr.Vfr + SetupMenuStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + CfrHelpersLib + DebugLib + DevicePathLib + HiiLib + HobLib + MemoryAllocationLib + VariablePolicyHelperLib + UefiHiiServicesLib + UefiLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + +[Guids] + gEfiCfrSetupMenuFormGuid + gEficorebootNvDataGuid + gEfiHiiPlatformSetupFormsetGuid ## CONSUMES ## GUID (Indicate the formset class guid to be displayed) + gEfiIfrTianoGuid ## CONSUMES ## GUID (Extended IFR Guid Opcode) + +[Protocols] + gEfiDevicePathProtocolGuid ## PRODUCES + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEdkiiVariablePolicyProtocolGuid ## SOMETIMES_CONSUMES + +[Depex] + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenu.c b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenu.c new file mode 100644 index 000000000000..3a069afb88ea --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenu.c @@ -0,0 +1,100 @@ +/** @file + A Setup Menu for configuring boot options defined by bootloader CFR. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SetupMenu.h" +#include +#include +#include +#include + +EDKII_VARIABLE_POLICY_PROTOCOL *mVariablePolicy = NULL; + +/** + This function installs the HII form. + +**/ +EFI_STATUS +EFIAPI +CfrSetupMenuEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&mVariablePolicy); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "CFR: Unable to lock variables!\n")); + } + + // + // Install Device Path and Config Access protocols to driver handle + // + mSetupMenuPrivate.DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &mSetupMenuPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mSetupMenuHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mSetupMenuPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data. + // + mSetupMenuPrivate.HiiHandle = HiiAddPackages ( + &mSetupMenuFormsetGuid, + mSetupMenuPrivate.DriverHandle, + SetupMenuVfrBin, + CfrSetupMenuDxeStrings, + NULL + ); + ASSERT (mSetupMenuPrivate.HiiHandle != NULL); + + // + // Insert runtime components from bootloader's CFR table. + // + CfrCreateRuntimeComponents (); + + return Status; +} + +/** + This function uninstalls the HII form. + +**/ +EFI_STATUS +EFIAPI +CfrSetupMenuUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + // + // Uninstall Device Path and Config Access protocols + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + mSetupMenuPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mSetupMenuHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mSetupMenuPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Remove our HII data + // + HiiRemovePackages (mSetupMenuPrivate.HiiHandle); + + return Status; +} diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenu.h b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenu.h new file mode 100644 index 000000000000..9754779e29e3 --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenu.h @@ -0,0 +1,141 @@ +/** @file + A Setup Menu for configuring boot options defined by bootloader CFR. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SETUP_MENU_H_ +#define _SETUP_MENU_H_ + +#include +#include +#include +#include +#include +#include "SetupMenuNVDataStruc.h" + +extern EDKII_VARIABLE_POLICY_PROTOCOL *mVariablePolicy; + +extern UINT8 SetupMenuVfrBin[]; + +#define SETUP_MENU_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('D', 'M', 'C', 'B') + +typedef struct { + UINTN Signature; + + // + // HII relative handles + // + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + // + // Produced protocols + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} SETUP_MENU_CALLBACK_DATA; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +extern SETUP_MENU_CALLBACK_DATA mSetupMenuPrivate; +extern EFI_GUID mSetupMenuFormsetGuid; +extern HII_VENDOR_DEVICE_PATH mSetupMenuHiiVendorDevicePath; + +/** + Create runtime components by iterating CFR forms. + +**/ +VOID +EFIAPI +CfrCreateRuntimeComponents ( + VOID + ); + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +SetupMenuExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +SetupMenuRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +/** + This function is invoked if user selected a interactive opcode from Setup Menu + Formset. If user set VBIOS, the new value is saved to EFI variable. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +SetupMenuCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +#endif diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuCfr.c b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuCfr.c new file mode 100644 index 000000000000..142b5e33914a --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuCfr.c @@ -0,0 +1,990 @@ +/** @file + A Setup Menu for configuring boot options defined by bootloader CFR. + This file parses CFR to produce HII IFR. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SetupMenu.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + CFR_VARBINARY records are used as option name and UI name and help text. + Convert one to formats used for EDK2 HII. + + Caller is responsible for freeing the UnicodeString pool. + +**/ +STATIC +VOID +EFIAPI +CfrConvertVarBinaryToStrings ( + IN CFR_VARBINARY *CfrString, + IN OUT CHAR16 **UnicodeString, + IN OUT EFI_STRING_ID *HiiStringId OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT ((CfrString != NULL) && (UnicodeString != NULL)); + + *UnicodeString = AllocatePool (CfrString->data_length * sizeof (CHAR16)); + ASSERT (*UnicodeString != NULL); + Status = AsciiStrToUnicodeStrS ( + (CHAR8 *)CfrString->data, + *UnicodeString, + CfrString->data_length + ); + ASSERT_EFI_ERROR (Status); + + if (HiiStringId != NULL) { + *HiiStringId = HiiSetString ( + mSetupMenuPrivate.HiiHandle, + 0, + *UnicodeString, + NULL + ); + ASSERT (*HiiStringId != 0); + } +} + +/** + CFR_VARBINARY records are used to store a list of dependency values. + Get a pointer to an array of enum values and its length. +**/ +STATIC +VOID +EFIAPI +CfrConvertVarBinaryToUint32Array ( + IN CFR_VARBINARY *CfrList, + IN OUT UINT32 **Array, + OUT UINT32 *ArrayLength + ) +{ + ASSERT ((CfrList != NULL) && (Array != NULL) && (ArrayLength != NULL)); + + *Array = (UINT32 *)CfrList->data; + *ArrayLength = CfrList->data_length / sizeof (UINT32); +} + +/** + Produce unconditional HII `*_IF` for CFR flags. + + Caller to close each `*_IF` with `HiiCreateEndOpCode()`. + +**/ +STATIC +VOID +EFIAPI +CfrProduceHiiForFlags ( + IN VOID *StartOpCodeHandle, + IN UINT8 OpCode + ) +{ + EFI_IFR_OP_HEADER IfOpHeader; + UINT8 *TempHiiBuffer; + EFI_IFR_OP_HEADER ConditionTrue; + + if ((OpCode != EFI_IFR_SUPPRESS_IF_OP) && (OpCode != EFI_IFR_GRAY_OUT_IF_OP)) { + return; + } + + IfOpHeader.OpCode = OpCode; + IfOpHeader.Length = sizeof (EFI_IFR_OP_HEADER); + // `if` statements are new scopes + IfOpHeader.Scope = 1; + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)&IfOpHeader, + sizeof (EFI_IFR_OP_HEADER) + ); + ASSERT (TempHiiBuffer != NULL); + + ConditionTrue.OpCode = EFI_IFR_TRUE_OP; + ConditionTrue.Length = sizeof (EFI_IFR_OP_HEADER); + // Same scope as above statement + ConditionTrue.Scope = 0; + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)&ConditionTrue, + sizeof (EFI_IFR_OP_HEADER) + ); + ASSERT (TempHiiBuffer != NULL); +} + +/** + Produce conditional HII `SUPPRESS_IF` based on a dependency: + + Caller to close each `SUPPRESS_IF` with `HiiCreateEndOpCode()`. + +**/ +STATIC +VOID +EFIAPI +CfrProduceHiiForDependency ( + IN VOID *StartOpCodeHandle, + IN UINTN DependencyId, + IN UINT32 *DepValues, + IN UINT32 NumDepValues + ) +{ + EFI_IFR_OP_HEADER OpHeader; + UINT8 *TempHiiBuffer; + UINTN EqIdValListSize; + EFI_IFR_EQ_ID_VAL_LIST *EqIdValList; + EFI_IFR_EQ_ID_VAL EqIdVal; + UINTN Index; + + OpHeader.OpCode = EFI_IFR_SUPPRESS_IF_OP; + OpHeader.Length = sizeof (EFI_IFR_OP_HEADER); + OpHeader.Scope = 1; + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)&OpHeader, + sizeof (EFI_IFR_OP_HEADER) + ); + ASSERT (TempHiiBuffer != NULL); + + if (NumDepValues != 0) { + EqIdValListSize = sizeof (EFI_IFR_EQ_ID_VAL_LIST) + ((NumDepValues - 1) * sizeof (UINT16)); + EqIdValList = AllocatePool (EqIdValListSize); + ASSERT (EqIdValList != NULL); + + EqIdValList->Header.OpCode = EFI_IFR_EQ_ID_VAL_LIST_OP; + EqIdValList->Header.Length = EqIdValListSize; + EqIdValList->Header.Scope = 1; + + EqIdValList->QuestionId = DependencyId; + EqIdValList->ListLength = NumDepValues; + for (Index = 0; Index < NumDepValues; Index++) { + EqIdValList->ValueList[Index] = (UINT16)*DepValues++; + } + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)EqIdValList, + EqIdValListSize + ); + ASSERT (TempHiiBuffer != NULL); + + FreePool (EqIdValList); + + OpHeader.OpCode = EFI_IFR_NOT_OP; + OpHeader.Length = sizeof (EFI_IFR_OP_HEADER); + OpHeader.Scope = 0; + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)&OpHeader, + sizeof (EFI_IFR_OP_HEADER) + ); + ASSERT (TempHiiBuffer != NULL); + } else { + EqIdVal.Header.OpCode = EFI_IFR_EQ_ID_VAL_OP; + EqIdVal.Header.Length = sizeof (EFI_IFR_EQ_ID_VAL); + EqIdVal.Header.Scope = 1; + EqIdVal.QuestionId = DependencyId; + EqIdVal.Value = 0; + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)&EqIdVal, + sizeof (EFI_IFR_EQ_ID_VAL) + ); + ASSERT (TempHiiBuffer != NULL); + } + + OpHeader.OpCode = EFI_IFR_END_OP; + OpHeader.Length = sizeof (EFI_IFR_OP_HEADER); + OpHeader.Scope = 0; + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)&OpHeader, + sizeof (EFI_IFR_OP_HEADER) + ); + ASSERT (TempHiiBuffer != NULL); +} + +/** + Produce variable and VARSTORE for CFR option name. + +**/ +STATIC +VOID +EFIAPI +CfrProduceStorageForOption ( + IN CFR_VARBINARY *CfrOptionName, + IN VOID *CfrOptionDefaultValue, + IN UINTN CfrOptionLength, + IN UINT8 OptionFlags, + IN VOID *StartOpCodeHandle, + IN UINTN QuestionIdVarStoreId + ) +{ + CHAR16 *VariableCfrName; + UINT32 VariableAttributes; + UINTN DataSize; + EFI_STATUS Status; + UINTN OptionNameLength; + UINTN VarStoreStructSize; + EFI_IFR_VARSTORE *VarStore; + UINT8 *TempHiiBuffer; + + // + // Initialise defaults for VARSTORE variable + // + CfrConvertVarBinaryToStrings (CfrOptionName, &VariableCfrName, NULL); + + // + // Variables can be runtime accessible later, if desired + // + VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS; + if (!(OptionFlags & CFR_OPTFLAG_VOLATILE)) { + VariableAttributes |= EFI_VARIABLE_NON_VOLATILE; + } + if (OptionFlags & CFR_OPTFLAG_RUNTIME) { + VariableAttributes |= EFI_VARIABLE_RUNTIME_ACCESS; + } + + DataSize = 0; + Status = gRT->GetVariable ( + VariableCfrName, + &gEficorebootNvDataGuid, + NULL, + &DataSize, + NULL + ); + if (Status == EFI_NOT_FOUND) { + DataSize = CfrOptionLength; + Status = gRT->SetVariable ( + VariableCfrName, + &gEficorebootNvDataGuid, + VariableAttributes, + DataSize, + CfrOptionDefaultValue + ); + ASSERT_EFI_ERROR (Status); + } + + if (OptionFlags & CFR_OPTFLAG_READONLY && mVariablePolicy != NULL) { + Status = RegisterBasicVariablePolicy ( + mVariablePolicy, + &gEficorebootNvDataGuid, + VariableCfrName, + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_NOW + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "CFR: Failed to lock variable \"%s\"!\n", VariableCfrName)); + } + } + + FreePool (VariableCfrName); + + // + // Build a `varstore` and copy it as raw HII opcodes. Then free this + // + /* Struct contains space for terminator only, allocate with name too */ + OptionNameLength = AsciiStrLen ((CHAR8 *)CfrOptionName->data); + VarStoreStructSize = sizeof (EFI_IFR_VARSTORE) + OptionNameLength; + ASSERT (VarStoreStructSize <= 0x7F); + if (VarStoreStructSize > 0x7F) { + DEBUG ((DEBUG_ERROR, "CFR: Option name length 0x%x is too long!\n", OptionNameLength)); + return; + } + + VarStore = AllocateZeroPool (VarStoreStructSize); + ASSERT (VarStore != NULL); + if (VarStore == NULL) { + DEBUG ((DEBUG_ERROR, "CFR: Failed to allocate memory for varstore!\n")); + return; + } + + VarStore->Header.OpCode = EFI_IFR_VARSTORE_OP; + VarStore->Header.Length = VarStoreStructSize; + + /* Direct mapping */ + VarStore->VarStoreId = QuestionIdVarStoreId; + VarStore->Size = CfrOptionLength; + + CopyMem (&VarStore->Guid, &gEficorebootNvDataGuid, sizeof (EFI_GUID)); + CopyMem (VarStore->Name, CfrOptionName->data, CfrOptionName->data_length); + + TempHiiBuffer = HiiCreateRawOpCodes ( + StartOpCodeHandle, + (UINT8 *)VarStore, + VarStoreStructSize + ); + ASSERT (TempHiiBuffer != NULL); + FreePool (VarStore); +} + +/** + Process one CFR form - its UI name - and create HII component. + Therefore, *do not* advanced index by the size field. + + It's currently too difficult to produce form HII IFR, because these + seem unable to be nested, so generating the VfrBin at runtime would be required. + However, maybe we'll look into that, or HII "scopes" later. + +**/ +STATIC +VOID +EFIAPI +CfrProcessFormOption ( + IN CFR_OPTION_FORM *Option, + IN VOID *StartOpCodeHandle, + IN OUT UINTN *ProcessedLength + ) +{ + CFR_VARBINARY *CfrFormName; + UINT32 *DepValues; + UINT32 NumDepValues; + CFR_VARBINARY *CfrDepValues; + CHAR16 *HiiFormNameString; + EFI_STRING_ID HiiFormNameStringId; + UINT8 *TempHiiBuffer; + + // + // Extract variable-length fields that follow the header + // + *ProcessedLength += sizeof (CFR_OPTION_FORM); + CfrFormName = CfrExtractVarBinary ((UINT8 *)Option, ProcessedLength, CB_TAG_CFR_VARCHAR_UI_NAME); + ASSERT (CfrFormName != NULL); + + // Dependency values are optional + DepValues = NULL; + NumDepValues = 0; + CfrDepValues = CfrExtractVarBinary ((UINT8 *)Option, ProcessedLength, CB_TAG_CFR_DEP_VALUES); + if (CfrDepValues != NULL) { + ASSERT (CfrDepValues->tag == CB_TAG_CFR_DEP_VALUES); + CfrConvertVarBinaryToUint32Array (CfrDepValues, &DepValues, &NumDepValues); + } + + DEBUG (( + DEBUG_INFO, + "CFR: Processing form \"%a\", size 0x%x\n", + CfrFormName->data, + Option->size + )); + + CfrConvertVarBinaryToStrings (CfrFormName, &HiiFormNameString, &HiiFormNameStringId); + FreePool (HiiFormNameString); + + if (Option->dependency_id) { + CfrProduceHiiForDependency ( + StartOpCodeHandle, + CFR_COMPONENT_START + Option->dependency_id, + DepValues, + NumDepValues + ); + } + + if (Option->flags & CFR_OPTFLAG_SUPPRESS) { + CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_SUPPRESS_IF_OP); + } + if (Option->flags & CFR_OPTFLAG_INACTIVE) { + CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_GRAY_OUT_IF_OP); + } + + TempHiiBuffer = HiiCreateSubTitleOpCode ( + StartOpCodeHandle, + HiiFormNameStringId, + STRING_TOKEN (STR_EMPTY_STRING), + 0, + 0 + ); + ASSERT (TempHiiBuffer != NULL); + + if (Option->flags & CFR_OPTFLAG_INACTIVE) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + if (Option->flags & CFR_OPTFLAG_SUPPRESS) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + + if (Option->dependency_id) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } +} + +/** + Process one CFR numeric option and create HII component. + +**/ +STATIC +VOID +EFIAPI +CfrProcessNumericOption ( + IN CFR_OPTION_NUMERIC *Option, + IN VOID *StartOpCodeHandle, + IN OUT UINTN *ProcessedLength + ) +{ + UINTN OptionProcessedLength; + CFR_VARBINARY *CfrOptionName; + CFR_VARBINARY *CfrDisplayName; + CFR_VARBINARY *CfrHelpText; + UINT32 *DepValues; + UINT32 NumDepValues; + CFR_VARBINARY *CfrDepValues; + UINTN QuestionIdVarStoreId; + UINT8 QuestionFlags; + VOID *DefaultOpCodeHandle; + UINT8 *TempHiiBuffer; + CHAR16 *HiiDisplayString; + EFI_STRING_ID HiiDisplayStringId; + CHAR16 *HiiHelpText; + EFI_STRING_ID HiiHelpTextId; + VOID *OptionOpCodeHandle; + CFR_ENUM_VALUE *CfrEnumValues; + CFR_VARBINARY *CfrEnumUiString; + CHAR16 *HiiEnumStrings; + EFI_STRING_ID HiiEnumStringsId; + + // + // Extract variable-length fields that follow the header + // + OptionProcessedLength = sizeof (CFR_OPTION_NUMERIC); + + CfrOptionName = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_OPT_NAME); + ASSERT (CfrOptionName != NULL); + CfrDisplayName = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_UI_NAME); + ASSERT (CfrDisplayName != NULL); + + // Help text is optional + CfrHelpText = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_UI_HELPTEXT); + if (CfrHelpText != NULL) { + ASSERT (CfrHelpText->tag == CB_TAG_CFR_VARCHAR_UI_HELPTEXT); + } + + // Dependency values are optional + DepValues = NULL; + NumDepValues = 0; + CfrDepValues = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_DEP_VALUES); + if (CfrDepValues != NULL) { + ASSERT (CfrDepValues->tag == CB_TAG_CFR_DEP_VALUES); + CfrConvertVarBinaryToUint32Array (CfrDepValues, &DepValues, &NumDepValues); + } + + DEBUG (( + DEBUG_INFO, + "CFR: Processing option \"%a\", size 0x%x\n", + CfrOptionName->data, + Option->size + )); + + // + // Processing start + // + QuestionIdVarStoreId = CFR_COMPONENT_START + Option->object_id; + CfrProduceStorageForOption ( + CfrOptionName, + &Option->default_value, + sizeof (Option->default_value), + Option->flags, + StartOpCodeHandle, + QuestionIdVarStoreId + ); + + QuestionFlags = EFI_IFR_FLAG_RESET_REQUIRED; + if (Option->flags & CFR_OPTFLAG_READONLY) { + QuestionFlags |= EFI_IFR_FLAG_READ_ONLY; + } + + if (Option->dependency_id) { + CfrProduceHiiForDependency ( + StartOpCodeHandle, + CFR_COMPONENT_START + Option->dependency_id, + DepValues, + NumDepValues + ); + } + + if (Option->flags & CFR_OPTFLAG_SUPPRESS) { + CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_SUPPRESS_IF_OP); + } + if (Option->flags & CFR_OPTFLAG_INACTIVE) { + CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_GRAY_OUT_IF_OP); + } + + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + + TempHiiBuffer = HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_TYPE_NUM_SIZE_32, + Option->default_value + ); + ASSERT (TempHiiBuffer != NULL); + + CfrConvertVarBinaryToStrings (CfrDisplayName, &HiiDisplayString, &HiiDisplayStringId); + FreePool (HiiDisplayString); + + if (CfrHelpText != NULL) { + CfrConvertVarBinaryToStrings (CfrHelpText, &HiiHelpText, &HiiHelpTextId); + FreePool (HiiHelpText); + } else { + HiiHelpTextId = STRING_TOKEN (STR_EMPTY_STRING); + } + + // + // Create HII opcodes, processing complete. + // + OptionOpCodeHandle = NULL; + if (Option->tag == CB_TAG_CFR_OPTION_ENUM) { + OptionOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionOpCodeHandle != NULL); + + while (OptionProcessedLength < Option->size) { + CfrEnumValues = (CFR_ENUM_VALUE *)((UINT8 *)Option + OptionProcessedLength); + ASSERT (CfrEnumValues->tag == CB_TAG_CFR_ENUM_VALUE); + + CfrEnumUiString = (CFR_VARBINARY *)((UINT8 *)CfrEnumValues + sizeof (CFR_ENUM_VALUE)); + ASSERT (CfrEnumUiString->tag == CB_TAG_CFR_VARCHAR_UI_NAME); + CfrConvertVarBinaryToStrings (CfrEnumUiString, &HiiEnumStrings, &HiiEnumStringsId); + FreePool (HiiEnumStrings); + + TempHiiBuffer = HiiCreateOneOfOptionOpCode ( + OptionOpCodeHandle, + HiiEnumStringsId, + 0, + EFI_IFR_TYPE_NUM_SIZE_32, + CfrEnumValues->value + ); + ASSERT (TempHiiBuffer != NULL); + + OptionProcessedLength += CfrEnumValues->size; + } + + TempHiiBuffer = HiiCreateOneOfOpCode ( + StartOpCodeHandle, + QuestionIdVarStoreId, + QuestionIdVarStoreId, + 0x0, + HiiDisplayStringId, + HiiHelpTextId, + QuestionFlags, + EFI_IFR_NUMERIC_SIZE_4, + OptionOpCodeHandle, + DefaultOpCodeHandle + ); + ASSERT (TempHiiBuffer != NULL); + } else if (Option->tag == CB_TAG_CFR_OPTION_NUMBER) { + TempHiiBuffer = HiiCreateNumericOpCode ( + StartOpCodeHandle, + QuestionIdVarStoreId, + QuestionIdVarStoreId, + 0x0, + HiiDisplayStringId, + HiiHelpTextId, + QuestionFlags, + EFI_IFR_NUMERIC_SIZE_4 | + ((Option->display_flags & CFR_NUM_OPT_DISPFLAG_HEX) ? + EFI_IFR_DISPLAY_UINT_HEX : EFI_IFR_DISPLAY_UINT_DEC), + Option->min, + Option->max, + Option->step, + DefaultOpCodeHandle + ); + ASSERT (TempHiiBuffer != NULL); + } else if (Option->tag == CB_TAG_CFR_OPTION_BOOL) { + // TODO: Or use ONE_OF instead? + TempHiiBuffer = HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + QuestionIdVarStoreId, + QuestionIdVarStoreId, + 0x0, + HiiDisplayStringId, + HiiHelpTextId, + QuestionFlags, + 0, + DefaultOpCodeHandle + ); + ASSERT (TempHiiBuffer != NULL); + } + + if (Option->flags & CFR_OPTFLAG_INACTIVE) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + if (Option->flags & CFR_OPTFLAG_SUPPRESS) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + + if (Option->dependency_id) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + + if (OptionOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (OptionOpCodeHandle); + } + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + + ASSERT (OptionProcessedLength == Option->size); + *ProcessedLength += Option->size; +} + +/** + Process one CFR character option and create HII component. + +**/ +STATIC +VOID +EFIAPI +CfrProcessCharacterOption ( + IN CFR_OPTION_VARCHAR *Option, + IN VOID *StartOpCodeHandle, + IN OUT UINTN *ProcessedLength + ) +{ + UINTN OptionProcessedLength; + CFR_VARBINARY *CfrOptionName; + CFR_VARBINARY *CfrDisplayName; + CFR_VARBINARY *CfrHelpText; + CFR_VARBINARY *CfrDefaultValue; + UINT32 *DepValues; + UINT32 NumDepValues; + CFR_VARBINARY *CfrDepValues; + UINTN QuestionIdVarStoreId; + CHAR16 *HiiDefaultValue; + EFI_STRING_ID HiiDefaultValueId; + UINTN HiiDefaultValueLengthChars; + CHAR16 *HiiDisplayString; + EFI_STRING_ID HiiDisplayStringId; + CHAR16 *HiiHelpText; + EFI_STRING_ID HiiHelpTextId; + UINT8 QuestionFlags; + VOID *DefaultOpCodeHandle; + UINT8 *TempHiiBuffer; + + // + // Extract variable-length fields that follow the header + // + ASSERT (sizeof (CFR_OPTION_VARCHAR) == sizeof (CFR_OPTION_COMMENT)); + OptionProcessedLength = sizeof (CFR_OPTION_VARCHAR); + + // Only true string options have variables + CfrOptionName = NULL; + if (Option->tag == CB_TAG_CFR_OPTION_VARCHAR) { + CfrDefaultValue = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_DEF_VALUE); + ASSERT (CfrDefaultValue != NULL); + + if (CfrDefaultValue->data_length > 0xFF) { + DEBUG ((DEBUG_ERROR, "CFR: Default value length 0x%x is too long!\n", CfrDefaultValue->data_length)); + *ProcessedLength += Option->size; + return; + } + + CfrOptionName = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_OPT_NAME); + ASSERT (CfrOptionName != NULL); + } + + CfrDisplayName = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_UI_NAME); + ASSERT (CfrDisplayName != NULL); + + // Help text is optional + CfrHelpText = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_UI_HELPTEXT); + if (CfrHelpText != NULL) { + ASSERT (CfrHelpText->tag == CB_TAG_CFR_VARCHAR_UI_HELPTEXT); + } + + // Dependency values are optional + DepValues = NULL; + NumDepValues = 0; + CfrDepValues = CfrExtractVarBinary ((UINT8 *)Option, &OptionProcessedLength, CB_TAG_CFR_DEP_VALUES); + if (CfrDepValues != NULL) { + ASSERT (CfrDepValues->tag == CB_TAG_CFR_DEP_VALUES); + CfrConvertVarBinaryToUint32Array (CfrDepValues, &DepValues, &NumDepValues); + } + + DEBUG (( + DEBUG_INFO, + "CFR: Processing option \"%a\", size 0x%x\n", + (CfrOptionName != NULL) ? CfrOptionName->data : CfrDisplayName->data, + Option->size + )); + + // + // Processing start + // + if (Option->tag == CB_TAG_CFR_OPTION_VARCHAR) { + QuestionIdVarStoreId = CFR_COMPONENT_START + Option->object_id; + + if (CfrDefaultValue->data_length > 1) { + CfrConvertVarBinaryToStrings (CfrDefaultValue, &HiiDefaultValue, &HiiDefaultValueId); + HiiDefaultValueLengthChars = CfrDefaultValue->data_length; + } else { + HiiDefaultValue = HiiGetString (mSetupMenuPrivate.HiiHandle, STRING_TOKEN (STR_INVALID_STRING), NULL); + HiiDefaultValueId = STRING_TOKEN (STR_INVALID_STRING); + HiiDefaultValueLengthChars = StrLen (HiiDefaultValue) + 1; + } + + CfrProduceStorageForOption ( + CfrOptionName, + HiiDefaultValue, + HiiDefaultValueLengthChars * sizeof (CHAR16), + Option->flags, + StartOpCodeHandle, + QuestionIdVarStoreId + ); + + if (HiiDefaultValue != NULL) { + FreePool (HiiDefaultValue); + } + } + + if (Option->dependency_id) { + CfrProduceHiiForDependency ( + StartOpCodeHandle, + CFR_COMPONENT_START + Option->dependency_id, + DepValues, + NumDepValues + ); + } + + if (Option->flags & CFR_OPTFLAG_SUPPRESS) { + CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_SUPPRESS_IF_OP); + } + if (Option->flags & CFR_OPTFLAG_INACTIVE) { + CfrProduceHiiForFlags (StartOpCodeHandle, EFI_IFR_GRAY_OUT_IF_OP); + } + + CfrConvertVarBinaryToStrings (CfrDisplayName, &HiiDisplayString, &HiiDisplayStringId); + FreePool (HiiDisplayString); + + if (CfrHelpText != NULL) { + CfrConvertVarBinaryToStrings (CfrHelpText, &HiiHelpText, &HiiHelpTextId); + FreePool (HiiHelpText); + } else { + HiiHelpTextId = STRING_TOKEN (STR_EMPTY_STRING); + } + + // + // Create HII opcodes, processing complete. + // + if (Option->tag == CB_TAG_CFR_OPTION_VARCHAR) { + QuestionFlags = EFI_IFR_FLAG_RESET_REQUIRED; + if (Option->flags & CFR_OPTFLAG_READONLY) { + QuestionFlags |= EFI_IFR_FLAG_READ_ONLY; + } + + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + + TempHiiBuffer = HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_TYPE_NUM_SIZE_16, + HiiDefaultValueId + ); + ASSERT (TempHiiBuffer != NULL); + + // TODO: User can adjust length of string? + TempHiiBuffer = HiiCreateStringOpCode ( + StartOpCodeHandle, + QuestionIdVarStoreId, + QuestionIdVarStoreId, + 0x0, + HiiDisplayStringId, + HiiHelpTextId, + QuestionFlags, + 0, + HiiDefaultValueLengthChars - 1, + HiiDefaultValueLengthChars - 1, + DefaultOpCodeHandle + ); + ASSERT (TempHiiBuffer != NULL); + + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + } else if (Option->tag == CB_TAG_CFR_OPTION_COMMENT) { + TempHiiBuffer = HiiCreateTextOpCode ( + StartOpCodeHandle, + HiiDisplayStringId, + HiiHelpTextId, + STRING_TOKEN (STR_EMPTY_STRING) + ); + ASSERT (TempHiiBuffer != NULL); + } + + if (Option->flags & CFR_OPTFLAG_INACTIVE) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + if (Option->flags & CFR_OPTFLAG_SUPPRESS) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + + if (Option->dependency_id) { + TempHiiBuffer = HiiCreateEndOpCode (StartOpCodeHandle); + ASSERT (TempHiiBuffer != NULL); + } + + ASSERT (OptionProcessedLength == Option->size); + *ProcessedLength += Option->size; +} + +/** + Create runtime components by iterating CFR forms. + +**/ +VOID +EFIAPI +CfrCreateRuntimeComponents ( + VOID + ) +{ + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_HOB_GUID_TYPE *GuidHob; + CFR_OPTION_FORM *CfrFormHob; + UINTN ProcessedLength; + CFR_OPTION_FORM *CfrFormData; + EFI_STATUS Status; + UINT8 *TempHiiBuffer; + + // + // Allocate GUIDed markers at runtime component offset in IFR + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + ASSERT (StartLabel != NULL); + + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_RT_COMP_START; + + EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + ASSERT (EndLabel != NULL); + + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_RT_COMP_END; + + // + // For each HOB, create forms + // + GuidHob = GetFirstGuidHob (&gEfiCfrSetupMenuFormGuid); + while (GuidHob != NULL) { + CfrFormHob = GET_GUID_HOB_DATA (GuidHob); + + ProcessedLength = 0; + CfrProcessFormOption ( + CfrFormHob, + StartOpCodeHandle, + &ProcessedLength + ); + + // + // Process form tree + // + while (ProcessedLength < CfrFormHob->size) { + CfrFormData = (CFR_OPTION_FORM *)((UINT8 *)CfrFormHob + ProcessedLength); + + switch (CfrFormData->tag) { + case CB_TAG_CFR_OPTION_FORM: + DEBUG ((DEBUG_INFO, "CFR: Nested form, will produce subtitle\n")); + CfrProcessFormOption ( + (CFR_OPTION_FORM *)CfrFormData, + StartOpCodeHandle, + &ProcessedLength + ); + break; + case CB_TAG_CFR_OPTION_ENUM: + case CB_TAG_CFR_OPTION_NUMBER: + case CB_TAG_CFR_OPTION_BOOL: + CfrProcessNumericOption ( + (CFR_OPTION_NUMERIC *)CfrFormData, + StartOpCodeHandle, + &ProcessedLength + ); + break; + case CB_TAG_CFR_OPTION_VARCHAR: + case CB_TAG_CFR_OPTION_COMMENT: + CfrProcessCharacterOption ( + (CFR_OPTION_VARCHAR *)CfrFormData, + StartOpCodeHandle, + &ProcessedLength + ); + break; + default: + DEBUG (( + DEBUG_ERROR, + "CFR: Offset 0x%x - Unexpected entry 0x%x (size 0x%x)!\n", + ProcessedLength, + CfrFormData->tag, + CfrFormData->size + )); + ProcessedLength += CfrFormData->size; + break; + } + } + + TempHiiBuffer = HiiCreateSubTitleOpCode ( + StartOpCodeHandle, + STRING_TOKEN (STR_EMPTY_STRING), + 0, + 0, + 0 + ); + ASSERT (TempHiiBuffer != NULL); + + GuidHob = GetNextGuidHob (&gEfiCfrSetupMenuFormGuid, GET_NEXT_HOB (GuidHob)); + } + + // + // Submit updates + // + Status = HiiUpdateForm ( + mSetupMenuPrivate.HiiHandle, + &mSetupMenuFormsetGuid, + SETUP_MENU_FORM_ID, + StartOpCodeHandle, + EndOpCodeHandle + ); + ASSERT_EFI_ERROR (Status); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuHii.c b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuHii.c new file mode 100644 index 000000000000..e725894a4010 --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuHii.c @@ -0,0 +1,303 @@ +/** @file + A Setup Menu for configuring boot options defined by bootloader CFR. + This file implements the HII Config Access protocol. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SetupMenu.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SETUP_MENU_CALLBACK_DATA mSetupMenuPrivate = { + SETUP_MENU_CALLBACK_DATA_SIGNATURE, + NULL, + NULL, + { + SetupMenuExtractConfig, + SetupMenuRouteConfig, + SetupMenuCallback + } +}; + +EFI_GUID mSetupMenuFormsetGuid = SETUP_MENU_FORMSET_GUID; + +HII_VENDOR_DEVICE_PATH mSetupMenuHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + SETUP_MENU_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + Parses a HII config string for the variable name. + 1. Find offset of "NAME=" value. + 2. Convert string value in Unicode-encoded hex to ASCII. + 3. Fixup Unicode string. + + It's assumed that "NAME=" has a value, hopefully tolerated. + It's assumed that ConfigRouting generates endian-specific strings, + so `SwapBytes16` is always required on `StrHexToBytes` byte-array. + + Caller to free VariableString pool. + +**/ +STATIC +CHAR16 * +EFIAPI +ConvertHiiConfigStringToVariableString ( + IN EFI_STRING HiiConfigString + ) +{ + EFI_STRING ConfigStringNameStart; + EFI_STRING ConfigStringNameEnd; + UINTN ConfigStringNameLengthChars; + UINTN ConvertStringLengthBytes; + UINTN VariableStringLengthChars; + CHAR16 *VariableString; + UINTN Index; + EFI_STATUS Status; + + ConfigStringNameStart = HiiConfigString; + + // + // Find the start and length of variable name in stringified hex + // + ConfigStringNameStart = StrStr (ConfigStringNameStart, L"&NAME="); + ASSERT (ConfigStringNameStart != NULL); + ConfigStringNameStart += StrLen (L"&NAME="); + + ConfigStringNameEnd = StrStr (ConfigStringNameStart, L"&"); + ASSERT (ConfigStringNameEnd != NULL); + + ConfigStringNameLengthChars = ConfigStringNameEnd - ConfigStringNameStart; + + // + // Convert stringified hex to bytes, then fixup to endian-correct string + // + ConvertStringLengthBytes = ConfigStringNameLengthChars / 2; + VariableStringLengthChars = ConvertStringLengthBytes / 2; + VariableString = AllocatePool (ConvertStringLengthBytes + sizeof (CHAR16)); + Status = StrHexToBytes ( + ConfigStringNameStart, + ConfigStringNameLengthChars, + (UINT8 *)VariableString, + ConvertStringLengthBytes + ); + ASSERT_EFI_ERROR (Status); + + VariableString[VariableStringLengthChars] = 0; + + for (Index = 0; Index < VariableStringLengthChars; Index++) { + VariableString[Index] = SwapBytes16 (VariableString[Index]); + } + + return VariableString; +} + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +SetupMenuExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + CHAR16 *VariableName; + VOID *VariableOption; + UINTN DataSize; + EFI_STATUS Status; + + if ((Request == NULL) || (Progress == NULL) || (Results == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + + // Get variable + VariableName = ConvertHiiConfigStringToVariableString (Request); + Status = GetVariable2 ( + VariableName, + &gEficorebootNvDataGuid, + &VariableOption, + &DataSize + ); + ASSERT_EFI_ERROR (Status); + + // Use HII helper to convert variable data to config + Status = gHiiConfigRouting->BlockToConfig ( + gHiiConfigRouting, + Request, + VariableOption, + DataSize, + Results, + Progress + ); + ASSERT_EFI_ERROR (Status); + + FreePool (VariableName); + if (VariableOption != NULL) { + FreePool (VariableOption); + } + + return Status; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +SetupMenuRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + CHAR16 *VariableName; + VOID *VariableOption; + UINTN DataSize; + UINT32 Attributes; + EFI_STATUS Status; + UINTN TempDataSize; + + if ((Configuration == NULL) || (Progress == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Configuration; + + // Get variable + VariableName = ConvertHiiConfigStringToVariableString (Configuration); + Status = GetVariable3 ( + VariableName, + &gEficorebootNvDataGuid, + &VariableOption, + &DataSize, + &Attributes + ); + ASSERT_EFI_ERROR (Status); + + // Use HII helper to convert updated config to variable data + TempDataSize = DataSize; + Status = gHiiConfigRouting->ConfigToBlock ( + gHiiConfigRouting, + Configuration, + VariableOption, + &TempDataSize, + Progress + ); + ASSERT_EFI_ERROR (Status); + + // Set variable + Status = gRT->SetVariable ( + VariableName, + &gEficorebootNvDataGuid, + Attributes, + DataSize, + VariableOption + ); + if (Status == EFI_WRITE_PROTECTED) { + Status = EFI_SUCCESS; + } + + ASSERT_EFI_ERROR (Status); + + FreePool (VariableName); + if (VariableOption != NULL) { + FreePool (VariableOption); + } + + return Status; +} + +/** + This function is invoked if user selected a interactive opcode from Setup Menu + Formset. If user set VBIOS, the new value is saved to EFI variable. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +SetupMenuCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuNVDataStruc.h b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuNVDataStruc.h new file mode 100644 index 000000000000..1e3b2a80e188 --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuNVDataStruc.h @@ -0,0 +1,22 @@ +/** @file + A Setup Menu for configuring boot options defined by bootloader CFR. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SETUPMENUNVDATASTRUC_H_ +#define _SETUPMENUNVDATASTRUC_H_ + +#define SETUP_MENU_FORMSET_GUID \ + { \ + 0x93E6FCD9, 0x8E17, 0x43DF, { 0xB7, 0xF0, 0x91, 0x3E, 0x58, 0xB1, 0xA7, 0x89 } \ + } + +#define SETUP_MENU_FORM_ID 0x0001 +#define LABEL_RT_COMP_START 0x0001 +#define CFR_COMPONENT_START 0x1000 +#define LABEL_RT_COMP_END 0xefff + +#endif diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuStrings.uni b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuStrings.uni new file mode 100644 index 000000000000..eff1ac840618 --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuStrings.uni @@ -0,0 +1,15 @@ +///** @file +// String definitions for the CFR Setup Menu. +//**/ + +#langdef en-US "English" +#langdef fr-FR "Français" + +#string STR_CFR_MENU_TITLE #language en-US "Platform Setup Menu" + #language fr-FR "Platform Setup Menu" +#string STR_CFR_MENU_HELP #language en-US "This menu lets you configure the bootloader options" + #language fr-FR "This menu lets you configure the bootloader options" +#string STR_EMPTY_STRING #language en-US "" + #language fr-FR "" +#string STR_INVALID_STRING #language en-US "INVALID" + #language fr-FR "INVALID" diff --git a/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuVfr.Vfr b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuVfr.Vfr new file mode 100644 index 000000000000..725c7682be84 --- /dev/null +++ b/UefiPayloadPkg/CfrSetupMenuDxe/SetupMenuVfr.Vfr @@ -0,0 +1,31 @@ +/** @file + Setup Menu formset. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include "SetupMenuNVDataStruc.h" + +formset + guid = SETUP_MENU_FORMSET_GUID, + title = STRING_TOKEN(STR_CFR_MENU_TITLE), + help = STRING_TOKEN(STR_CFR_MENU_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + form formid = SETUP_MENU_FORM_ID, + title = STRING_TOKEN(STR_CFR_MENU_TITLE); + + /** + Sections for runtime components + + **/ + label LABEL_RT_COMP_START; + label LABEL_RT_COMP_END; + + endform; + +endformset; diff --git a/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.c b/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.c new file mode 100644 index 000000000000..199dcb2add2d --- /dev/null +++ b/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.c @@ -0,0 +1,605 @@ +/** @file + Enroll default PK, KEK, DB and DBX + + Copyright (C) 2014, Red Hat, Inc. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "EnrollDefaultKeys.h" + +/** + Enroll a set of certificates in a global variable, overwriting it. + + The variable will be rewritten with NV+BS+RT+AT attributes. + + @param[in] VariableName The name of the variable to overwrite. + + @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to + overwrite. + + @param[in] CertType The GUID determining the type of all the + certificates in the set that is passed in. For + example, gEfiCertX509Guid stands for DER-encoded + X.509 certificates, while gEfiCertSha256Guid stands + for SHA256 image hashes. + + @param[in] ... A list of + + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST EFI_GUID *OwnerGuid + + triplets. If the first component of a triplet is + NULL, then the other two components are not + accessed, and processing is terminated. The list of + certificates is enrolled in the variable specified, + overwriting it. The OwnerGuid component identifies + the agent installing the certificate. + + @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert + value is NULL), or one of the CertSize values + is 0, or one of the CertSize values would + overflow the accumulated UINT32 data size. + + @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable + payload. + + @retval EFI_SUCCESS Enrollment successful; the variable has been + overwritten (or created). + + @return Error codes from gRT->GetTime() and + gRT->SetVariable(). + **/ +STATIC +EFI_STATUS +EFIAPI +EnrollListOfCerts ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN EFI_GUID *CertType, + ... + ) +{ + UINTN DataSize; + SINGLE_HEADER *SingleHeader; + REPEATING_HEADER *RepeatingHeader; + VA_LIST Marker; + CONST UINT8 *Cert; + EFI_STATUS Status; + UINT8 *Data; + UINT8 *Position; + + Status = EFI_SUCCESS; + + // + // compute total size first, for UINT32 range check, and allocation + // + DataSize = sizeof *SingleHeader; + VA_START (Marker, CertType); + for (Cert = VA_ARG (Marker, CONST UINT8 *); + Cert != NULL; + Cert = VA_ARG (Marker, CONST UINT8 *)) { + UINTN CertSize; + + CertSize = VA_ARG (Marker, UINTN); + (VOID)VA_ARG (Marker, CONST EFI_GUID *); + + if (CertSize == 0 || + CertSize > MAX_UINT32 - sizeof *RepeatingHeader || + DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) { + Status = EFI_INVALID_PARAMETER; + break; + } + DataSize += sizeof *RepeatingHeader + CertSize; + } + VA_END (Marker); + + if (DataSize == sizeof *SingleHeader) { + Status = EFI_INVALID_PARAMETER; + } + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: Invalid certificate parameters\n")); + goto Out; + } + + Data = AllocatePool (DataSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Out; + } + + Position = Data; + + SingleHeader = (SINGLE_HEADER *)Position; + Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "EnrollDefaultKeys: GetTime failed\n")); + // Fill in dummy values + SingleHeader->TimeStamp.Year = 2018; + SingleHeader->TimeStamp.Month = 1; + SingleHeader->TimeStamp.Day = 1; + SingleHeader->TimeStamp.Hour = 0; + SingleHeader->TimeStamp.Minute = 0; + SingleHeader->TimeStamp.Second = 0; + Status = EFI_SUCCESS; + } + SingleHeader->TimeStamp.Pad1 = 0; + SingleHeader->TimeStamp.Nanosecond = 0; + SingleHeader->TimeStamp.TimeZone = 0; + SingleHeader->TimeStamp.Daylight = 0; + SingleHeader->TimeStamp.Pad2 = 0; + + // + // This looks like a bug in edk2. According to the UEFI specification, + // dwLength is "The length of the entire certificate, including the length of + // the header, in bytes". That shouldn't stop right after CertType -- it + // should include everything below it. + // + SingleHeader->dwLength = sizeof *SingleHeader - sizeof SingleHeader->TimeStamp; + SingleHeader->wRevision = 0x0200; + SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID; + CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid); + Position += sizeof *SingleHeader; + + VA_START (Marker, CertType); + for (Cert = VA_ARG (Marker, CONST UINT8 *); + Cert != NULL; + Cert = VA_ARG (Marker, CONST UINT8 *)) { + UINTN CertSize; + CONST EFI_GUID *OwnerGuid; + + CertSize = VA_ARG (Marker, UINTN); + OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *); + + RepeatingHeader = (REPEATING_HEADER *)Position; + CopyGuid (&RepeatingHeader->SignatureType, CertType); + RepeatingHeader->SignatureListSize = + (UINT32)(sizeof *RepeatingHeader + CertSize); + RepeatingHeader->SignatureHeaderSize = 0; + RepeatingHeader->SignatureSize = + (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize); + CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid); + Position += sizeof *RepeatingHeader; + + CopyMem (Position, Cert, CertSize); + Position += CertSize; + } + VA_END (Marker); + + ASSERT (Data + DataSize == Position); + + Status = gRT->SetVariable (VariableName, VendorGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS), + DataSize, Data); + + FreePool (Data); + +Out: + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName, + VendorGuid, Status)); + } + return Status; +} + +/** + Read a UEFI variable into a caller-allocated buffer, enforcing an exact size. + + @param[in] VariableName The name of the variable to read; passed to + gRT->GetVariable(). + + @param[in] VendorGuid The vendor (namespace) GUID of the variable to read; + passed to gRT->GetVariable(). + + @param[out] Data The caller-allocated buffer that is supposed to + receive the variable's contents. On error, the + contents of Data are indeterminate. + + @param[in] DataSize The size in bytes that the caller requires the UEFI + variable to have. The caller is responsible for + providing room for DataSize bytes in Data. + + @param[in] AllowMissing If FALSE, the variable is required to exist. If + TRUE, the variable is permitted to be missing. + + @retval EFI_SUCCESS The UEFI variable exists, has the required size + (DataSize), and has been read into Data. + + @retval EFI_SUCCESS The UEFI variable doesn't exist, and + AllowMissing is TRUE. DataSize bytes in Data + have been zeroed out. + + @retval EFI_NOT_FOUND The UEFI variable doesn't exist, and + AllowMissing is FALSE. + + @retval EFI_BUFFER_TOO_SMALL The UEFI variable exists, but its size is + greater than DataSize. + + @retval EFI_PROTOCOL_ERROR The UEFI variable exists, but its size is + smaller than DataSize. + + @return Error codes propagated from gRT->GetVariable(). + +**/ +STATIC +EFI_STATUS +EFIAPI +GetExact ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VOID *Data, + IN UINTN DataSize, + IN BOOLEAN AllowMissing + ) +{ + UINTN Size; + EFI_STATUS Status; + + Size = DataSize; + Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND && AllowMissing) { + ZeroMem (Data, DataSize); + return EFI_SUCCESS; + } + + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: GetVariable(\"%s\", %g): %r\n", VariableName, + VendorGuid, Status)); + return Status; + } + + if (Size != DataSize) { + DEBUG ((EFI_D_INFO, "EnrollDefaultKeys: GetVariable(\"%s\", %g): expected size 0x%Lx, " + "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size)); + return EFI_PROTOCOL_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Populate a SETTINGS structure from the underlying UEFI variables. + + The following UEFI variables are standard variables: + - L"SetupMode" (EFI_SETUP_MODE_NAME) + - L"SecureBoot" (EFI_SECURE_BOOT_MODE_NAME) + - L"VendorKeys" (EFI_VENDOR_KEYS_VARIABLE_NAME) + + The following UEFI variables are edk2 extensions: + - L"SecureBootEnable" (EFI_SECURE_BOOT_ENABLE_NAME) + - L"CustomMode" (EFI_CUSTOM_MODE_NAME) + + The L"SecureBootEnable" UEFI variable is permitted to be missing, in which + case the corresponding field in the SETTINGS object will be zeroed out. The + rest of the covered UEFI variables are required to exist; otherwise, the + function will fail. + + @param[out] Settings The SETTINGS object to fill. + @param[in] AllowMissing If FALSE, the required variables must exist; if + TRUE, the function can succeed even if some + variables are missing. + + @retval EFI_SUCCESS Settings has been populated. + + @return Error codes propagated from the GetExact() function. The + contents of Settings are indeterminate. +**/ +STATIC +EFI_STATUS +EFIAPI +GetSettings ( + OUT SETTINGS *Settings, + BOOLEAN AllowMissing + ) +{ + EFI_STATUS Status; + + ZeroMem (Settings, sizeof(SETTINGS)); + + Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, + &Settings->SetupMode, sizeof Settings->SetupMode, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, + &Settings->SecureBoot, sizeof Settings->SecureBoot, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable, + sizeof Settings->SecureBootEnable, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + &Settings->CustomMode, sizeof Settings->CustomMode, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, + &Settings->VendorKeys, sizeof Settings->VendorKeys, AllowMissing); + return Status; +} + +/** + + Print the contents of a SETTINGS structure to the UEFI console. + + @param[in] Settings The SETTINGS object to print the contents of. + +**/ +STATIC +VOID +EFIAPI +PrintSettings ( + IN CONST SETTINGS *Settings + ) +{ + DEBUG ((EFI_D_INFO, "EnrollDefaultKeys: SetupMode=%d SecureBoot=%d SecureBootEnable=%d " + "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot, + Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys)); +} + +/** + Install SecureBoot certificates once the VariableDriver is running. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +EnrollDefaultKeys ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *Protocol; + SETTINGS Settings; + + UINT8 *DbMicrosoftUefi2011 = 0; + UINTN DbMicrosoftUefi2011Size; + UINT8 *DbMicrosoftUefi2023 = 0; + UINTN DbMicrosoftUefi2023Size; + UINT8 *DbMicrosoftWin2011 = 0; + UINTN DbMicrosoftWin2011Size; + UINT8 *DbMicrosoftWinuefi2023 = 0; + UINTN DbMicrosoftWinuefi2023Size; + UINT8 *DbxMicrosoftUpdate = 0; + UINTN DbxMicrosoftUpdateSize; + UINT8 *KekMicrosoft2011 = 0; + UINTN KekMicrosoft2011Size; + UINT8 *KekMicrosoft2023 = 0; + UINTN KekMicrosoft2023Size; + UINT8 *KekMicrosoftUefi2023 = 0; + UINTN KekMicrosoftUefi2023Size; + UINT8 *PkMicrosoftOem2023 = 0; + UINTN PkMicrosoftOem2023Size; + + Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol); + if (EFI_ERROR (Status)) { + return; + } + + Status = GetSettings (&Settings, TRUE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: Failed to get current settings\n")); + return; + } + + if (Settings.SetupMode != SETUP_MODE) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: already in User Mode\n")); + return; + } + PrintSettings (&Settings); + + if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) { + Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE; + Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS), + sizeof Settings.CustomMode, &Settings.CustomMode); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + } + + Status = GetSectionFromAnyFv(&gMicrosoftDbUefi2011Guid, EFI_SECTION_RAW, 0, (void **)&DbMicrosoftUefi2011, &DbMicrosoftUefi2011Size); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftDbUefi2023Guid, EFI_SECTION_RAW, 0, (void **)&DbMicrosoftUefi2023, &DbMicrosoftUefi2023Size); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftDbWin2011Guid, EFI_SECTION_RAW, 0, (void **)&DbMicrosoftWin2011, &DbMicrosoftWin2011Size); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftDbWinUefi2023Guid, EFI_SECTION_RAW, 0, (void **)&DbMicrosoftWinuefi2023, &DbMicrosoftWinuefi2023Size); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftDbxUpdateGuid, EFI_SECTION_RAW, 0, (void **)&DbxMicrosoftUpdate, &DbxMicrosoftUpdateSize); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftKek2011Guid, EFI_SECTION_RAW, 0, (void **)&KekMicrosoft2011, &KekMicrosoft2011Size); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftKek2023Guid, EFI_SECTION_RAW, 0, (void **)&KekMicrosoft2023, &KekMicrosoft2023Size); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftKekUefi2023Guid, EFI_SECTION_RAW, 0, (void **)&KekMicrosoftUefi2023, &KekMicrosoftUefi2023Size); + ASSERT_EFI_ERROR(Status); + Status = GetSectionFromAnyFv(&gMicrosoftPkOem2023Guid, EFI_SECTION_RAW, 0, (void **)&PkMicrosoftOem2023, &PkMicrosoftOem2023Size); + ASSERT_EFI_ERROR(Status); + + Status = gRT->SetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS), + DbxMicrosoftUpdateSize, DbxMicrosoftUpdate); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + &gEfiCertX509Guid, + DbMicrosoftUefi2011, DbMicrosoftUefi2011Size, DbMicrosoftWinuefi2023Size, + DbMicrosoftUefi2023, DbMicrosoftUefi2023Size, DbMicrosoftWinuefi2023Size, + DbMicrosoftWin2011, DbMicrosoftWin2011Size, DbMicrosoftWinuefi2023Size, + DbMicrosoftWinuefi2023, DbMicrosoftWinuefi2023Size, DbMicrosoftWinuefi2023Size, + NULL); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + &gEfiCertX509Guid, + KekMicrosoft2011, KekMicrosoft2011Size, gMicrosoftVendorGuid, + KekMicrosoft2023, KekMicrosoft2023Size, gMicrosoftVendorGuid, + KekMicrosoftUefi2023, KekMicrosoftUefi2023Size, gMicrosoftVendorGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid, + &gEfiCertX509Guid, + PkMicrosoftOem2023, PkMicrosoftOem2023Size, gMicrosoftVendorGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + FreePool(DbMicrosoftUefi2011); + FreePool(DbMicrosoftUefi2023); + FreePool(DbMicrosoftWin2011); + FreePool(DbMicrosoftWinuefi2023); + FreePool(DbxMicrosoftUpdate); + FreePool(KekMicrosoft2011); + FreePool(KekMicrosoft2023); + FreePool(KekMicrosoftUefi2023); + FreePool(PkMicrosoftOem2023); + + Settings.CustomMode = STANDARD_SECURE_BOOT_MODE; + Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof Settings.CustomMode, &Settings.CustomMode); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + // FIXME: Force SecureBoot to ON. The AuthService will do this if authenticated variables + // are supported, which aren't as the SMM handler isn't able to verify them. + + Settings.SecureBootEnable = SECURE_BOOT_DISABLE; + Status = gRT->SetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof Settings.SecureBootEnable, &Settings.SecureBootEnable); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + Settings.SecureBoot = SECURE_BOOT_DISABLE; + Status = gRT->SetVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof Settings.SecureBoot, &Settings.SecureBoot); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + Status = GetSettings (&Settings, FALSE); + ASSERT_EFI_ERROR (Status); + + // + // Final sanity check: + // + // [SetupMode] + // (read-only, standardized by UEFI) + // / \_ + // 0 1, default + // / \_ + // PK enrolled no PK enrolled yet, + // (this is called "User Mode") PK enrollment possible + // | + // | + // [SecureBootEnable] + // (read-write, edk2-specific, boot service only) + // / \_ + // 0 1, default + // / \_ + // [SecureBoot]=0 [SecureBoot]=1 + // (read-only, standardized by UEFI) (read-only, standardized by UEFI) + // images are not verified images are verified, platform is + // operating in Secure Boot mode + // | + // | + // [CustomMode] + // (read-write, edk2-specific, boot service only) + // / \_ + // 0, default 1 + // / \_ + // PK, KEK, db, dbx PK, KEK, db, dbx + // updates are verified updates are not verified + // + + PrintSettings (&Settings); + + if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 || + Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 || + Settings.VendorKeys != 0) { + DEBUG ((DEBUG_ERROR, "EnrollDefaultKeys: disabled\n")); + return; + } + + DEBUG ((EFI_D_INFO, "EnrollDefaultKeys: SecureBoot enabled\n")); +} + +EFI_STATUS +EFIAPI +DriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + VOID *Registration; + + DEBUG ((DEBUG_INFO, "EnrollDefaultKeys hook\n")); + + // + // Create event callback, because we need access variable on SecureBootPolicyVariable + // We should use VariableWriteArch instead of VariableArch, because Variable driver + // may update SecureBoot value based on last setting. + // + EfiCreateProtocolNotifyEvent ( + &gEfiVariableWriteArchProtocolGuid, + TPL_CALLBACK, + EnrollDefaultKeys, + NULL, + &Registration); + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.h b/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.h new file mode 100644 index 000000000000..abfaf3ab6577 --- /dev/null +++ b/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.h @@ -0,0 +1,121 @@ +/** @file + Type definitions and object declarations for the EnrollDefaultKeys + application. + + Copyright (C) 2014-2019, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef ENROLL_DEFAULT_KEYS_H_ +#define ENROLL_DEFAULT_KEYS_H_ + +#include + +// +// Convenience structure types for constructing "signature lists" for +// authenticated UEFI variables. +// +// The most important thing about the variable payload is that it is a list of +// lists, where the element size of any given *inner* list is constant. +// +// Since X509 certificates vary in size, each of our *inner* lists will contain +// one element only (one X.509 certificate). This is explicitly mentioned in +// the UEFI specification, in "28.4.1 Signature Database", in a Note. +// +// The list structure looks as follows: +// +// struct EFI_VARIABLE_AUTHENTICATION_2 { | +// struct EFI_TIME { | +// UINT16 Year; | +// UINT8 Month; | +// UINT8 Day; | +// UINT8 Hour; | +// UINT8 Minute; | +// UINT8 Second; | +// UINT8 Pad1; | +// UINT32 Nanosecond; | +// INT16 TimeZone; | +// UINT8 Daylight; | +// UINT8 Pad2; | +// } TimeStamp; | +// | +// struct WIN_CERTIFICATE_UEFI_GUID { | | +// struct WIN_CERTIFICATE { | | +// UINT32 dwLength; ----------------------------------------+ | +// UINT16 wRevision; | | +// UINT16 wCertificateType; | | +// } Hdr; | +- DataSize +// | | +// EFI_GUID CertType; | | +// UINT8 CertData[1] = { <--- "struct hack" | | +// struct EFI_SIGNATURE_LIST { | | | +// EFI_GUID SignatureType; | | | +// UINT32 SignatureListSize; -------------------------+ | | +// UINT32 SignatureHeaderSize; | | | +// UINT32 SignatureSize; ---------------------------+ | | | +// UINT8 SignatureHeader[SignatureHeaderSize]; | | | | +// v | | | +// struct EFI_SIGNATURE_DATA { | | | | +// EFI_GUID SignatureOwner; | | | | +// UINT8 SignatureData[1] = { <--- "struct hack" | | | | +// X.509 payload | | | | +// } | | | | +// } Signatures[]; | | | +// } SigLists[]; | | +// }; | | +// } AuthInfo; | | +// }; | +// +// Given that the "struct hack" invokes undefined behavior (which is why C99 +// introduced the flexible array member), and because subtracting those pesky +// sizes of 1 is annoying, and because the format is fully specified in the +// UEFI specification, we'll introduce two matching convenience structures that +// are customized for our X.509 purposes. +// +#pragma pack (1) +typedef struct { + EFI_TIME TimeStamp; + + // + // dwLength covers data below + // + UINT32 dwLength; + UINT16 wRevision; + UINT16 wCertificateType; + EFI_GUID CertType; +} SINGLE_HEADER; + +typedef struct { + // + // SignatureListSize covers data below + // + EFI_GUID SignatureType; + UINT32 SignatureListSize; + UINT32 SignatureHeaderSize; // constant 0 + UINT32 SignatureSize; + + // + // SignatureSize covers data below + // + EFI_GUID SignatureOwner; + + // + // X.509 certificate follows + // +} REPEATING_HEADER; +#pragma pack () + +// +// A structure that collects the values of UEFI variables related to Secure +// Boot. +// +typedef struct { + UINT8 SetupMode; + UINT8 SecureBoot; + UINT8 SecureBootEnable; + UINT8 CustomMode; + UINT8 VendorKeys; +} SETTINGS; + +#endif /* ENROLL_DEFAULT_KEYS_H_ */ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf b/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf new file mode 100644 index 000000000000..e639084cb84f --- /dev/null +++ b/UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf @@ -0,0 +1,63 @@ +## @file +# This file handels SecureBoot setup. +# +# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EnrollDefaultKeys + FILE_GUID = 14693BD4-D114-4177-979E-37F279BAD620 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 0.1 + ENTRY_POINT = DriverEntry + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + EnrollDefaultKeys.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[Guids] + gEfiCertPkcs7Guid + gEfiCertX509Guid + gEfiCustomModeEnableGuid + gEfiGlobalVariableGuid + gEfiImageSecurityDatabaseGuid + gEfiSecureBootEnableDisableGuid + gMicrosoftVendorGuid + gMicrosoftDbxUpdateGuid + gMicrosoftDbUefi2011Guid + gMicrosoftDbWin2011Guid + gMicrosoftDbUefi2023Guid + gMicrosoftDbWinUefi2023Guid + gMicrosoftKek2011Guid + gMicrosoftKek2023Guid + gMicrosoftKekUefi2023Guid + gMicrosoftPkOem2023Guid + +[LibraryClasses] + BaseMemoryLib + DebugLib + DxeServicesLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Protocols] + gEfiVariableWriteArchProtocolGuid ## CONSUMES + +[Depex] + TRUE diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2011.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2011.der new file mode 100644 index 000000000000..9aa6ac6c79b2 Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2011.der differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2023.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2023.der new file mode 100644 index 000000000000..39a91b31730a Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2023.der differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_2011.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_2011.der new file mode 100644 index 000000000000..a6d001c21938 Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_2011.der differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_uefi_2023.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_uefi_2023.der new file mode 100644 index 000000000000..4c5430b28340 Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_uefi_2023.der differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/dbx_microsoft_update.bin b/UefiPayloadPkg/EnrollDefaultKeys/keys/dbx_microsoft_update.bin new file mode 100644 index 000000000000..811e27eb39e1 Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/dbx_microsoft_update.bin differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2011.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2011.der new file mode 100644 index 000000000000..2787083e0cb6 Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2011.der differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2023.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2023.der new file mode 100644 index 000000000000..e6ffb4f975fa Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2023.der differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_uefi_2023.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_uefi_2023.der new file mode 100644 index 000000000000..bfdda98f6df3 Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_uefi_2023.der differ diff --git a/UefiPayloadPkg/EnrollDefaultKeys/keys/pk_microsoft_oem_2023.der b/UefiPayloadPkg/EnrollDefaultKeys/keys/pk_microsoft_oem_2023.der new file mode 100644 index 000000000000..0154225b7199 Binary files /dev/null and b/UefiPayloadPkg/EnrollDefaultKeys/keys/pk_microsoft_oem_2023.der differ diff --git a/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c b/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c index 39ad03fe32c3..74c1ce12cffd 100644 --- a/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c +++ b/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c @@ -435,8 +435,9 @@ GraphicsOutputDriverBindingStart ( } if (DeviceInfo->BarIndex == MAX_UINT8) { - if (Resources->AddrRangeMin == GraphicsInfo->FrameBufferBase) { - FrameBufferBase = Resources->AddrRangeMin; + if (Resources->AddrRangeMin <= GraphicsInfo->FrameBufferBase + && Resources->AddrRangeMin + Resources->AddrLen >= GraphicsInfo->FrameBufferBase + GraphicsInfo->FrameBufferSize ) { + FrameBufferBase = GraphicsInfo->FrameBufferBase; break; } } else { diff --git a/UefiPayloadPkg/Include/Coreboot.h b/UefiPayloadPkg/Include/Coreboot.h index 1b05f15fe5d3..7cf22967a041 100644 --- a/UefiPayloadPkg/Include/Coreboot.h +++ b/UefiPayloadPkg/Include/Coreboot.h @@ -261,8 +261,19 @@ struct cb_smmstorev2 { UINT8 apm_cmd; /* The command byte to write to the APM I/O port to communicate with the store */ UINT8 unused[3]; /* Set to zero */ + UINT64 mmap_addr_ext; /* 64-bit MMIO address of the store for read only access. + * Only available when size field >= 40. */ } __attribute__ ((packed)); +#define CB_TAG_CFR_ROOT 0x0047 +struct cb_cfr { + UINT32 tag; + UINT32 size; + UINT32 version; + UINT32 checksum; /* Of the following data only; excludes these 3 fields */ + /* CFR_FORM forms[] */ +}; + /* Helpful macros */ #define MEM_RANGE_COUNT(_rec) \ @@ -274,4 +285,30 @@ struct cb_smmstorev2 { typedef struct cb_memory CB_MEMORY; +#define CB_TAG_TPM_PPI_HANDOFF 0x003a + +enum lb_tmp_ppi_tpm_version { + LB_TPM_VERSION_UNSPEC = 0, + LB_TPM_VERSION_TPM_VERSION_1_2, + LB_TPM_VERSION_TPM_VERSION_2, +}; + +/* + * Handoff buffer for TPM Physical Presence Interface. + * * ppi_address Pointer to PPI buffer shared with ACPI + * The layout of the buffer matches the QEMU virtual memory device + * that is generated by QEMU. + * See files 'hw/i386/acpi-build.c' and 'include/hw/acpi/tpm.h' + * for details. + * * tpm_version TPM version: 1 for TPM1.2, 2 for TPM2.0 + * * ppi_version BCD encoded version of TPM PPI interface + */ +struct cb_tpm_physical_presence { + UINT32 tag; + UINT32 size; + UINT32 ppi_address; /* Address of ACPI PPI communication buffer */ + UINT8 tpm_version; /* 1: TPM1.2, 2: TPM2.0 */ + UINT8 ppi_version; /* BCD encoded */ +} __attribute__((packed)); + #endif // _COREBOOT_PEI_H_INCLUDED_ diff --git a/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h b/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h index 2f79c10f51d5..8d09447b3aa5 100644 --- a/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h +++ b/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h @@ -25,6 +25,8 @@ typedef struct { UINT64 ResetRegAddress; UINT64 PcieBaseAddress; UINT64 PcieBaseSize; + UINT8 TPM20Present; + UINT8 TPM12Present; } ACPI_BOARD_INFO; #endif diff --git a/UefiPayloadPkg/Include/Guid/CfrSetupMenuGuid.h b/UefiPayloadPkg/Include/Guid/CfrSetupMenuGuid.h new file mode 100644 index 000000000000..570075681303 --- /dev/null +++ b/UefiPayloadPkg/Include/Guid/CfrSetupMenuGuid.h @@ -0,0 +1,153 @@ +/** @file + This file defines the hob structure for bootloader's CFR option menu. + + Copyright (c) 2023, 9elements GmbH. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __CFR_SETUP_MENU_GUID_H__ +#define __CFR_SETUP_MENU_GUID_H__ + +#define CB_CFR_VERSION 0x00000000 + +/// +/// CFR options form GUID +/// +extern EFI_GUID gEfiCfrSetupMenuFormGuid; + +/* + * The following tags are for CFR (Cursed Form Representation) entries. + * + * CFR records form a tree structure. The size of a record includes + * the size of its own fields plus the size of all children records. + * CFR tags can appear multiple times except for `LB_TAG_CFR` which + * is used for the root record. + * + * The following structures have comments that describe the supported + * children records. These comments cannot be replaced with code! The + * structures are variable-length, so the offsets won't be valid most + * of the time. Besides, the implementation uses `sizeof()` to obtain + * the size of the "record header" (the fixed-length members); adding + * the children structures as struct members will increase the length + * returned by `sizeof()`, which complicates things for zero reason. + * + * TODO: "This should be documentation instead." + */ +enum cfr_option_flags { + CFR_OPTFLAG_READONLY = 1 << 0, + CFR_OPTFLAG_INACTIVE = 1 << 1, + CFR_OPTFLAG_SUPPRESS = 1 << 2, + CFR_OPTFLAG_VOLATILE = 1 << 3, + CFR_OPTFLAG_RUNTIME = 1 << 4, +}; + +#define CB_TAG_CFR_VARCHAR_OPT_NAME 0x0007 +#define CB_TAG_CFR_VARCHAR_UI_NAME 0x0008 +#define CB_TAG_CFR_VARCHAR_UI_HELPTEXT 0x0009 +#define CB_TAG_CFR_VARCHAR_DEF_VALUE 0x000a +#define CB_TAG_CFR_DEP_VALUES 0x000c +#pragma pack (1) +typedef struct { + UINT32 tag; /* + * CFR_TAG_VARCHAR_OPT_NAME, CFR_TAG_VARCHAR_UI_NAME, + * CFR_TAG_VARCHAR_UI_HELPTEXT, CFR_TAG_VARCHAR_DEF_VALUE + * or CFR_TAG_DEP_VALUES + */ + UINT32 size; /* Length of the entire structure */ + UINT32 data_length; /* Length of data, including NULL terminator for strings */ + UINT8 data[]; +} CFR_VARBINARY; + +#define CB_TAG_CFR_ENUM_VALUE 0x0002 +typedef struct { + UINT32 tag; /* CFR_TAG_ENUM_VALUE */ + UINT32 size; + UINT32 value; + /* + * CFR_UI_NAME ui_name + */ +} CFR_ENUM_VALUE; + +enum cfr_numeric_option_display_flags { + CFR_NUM_OPT_DISPFLAG_HEX = 1 << 0, +}; + +#define CB_TAG_CFR_OPTION_ENUM 0x0003 +#define CB_TAG_CFR_OPTION_NUMBER 0x0004 +#define CB_TAG_CFR_OPTION_BOOL 0x0005 +typedef struct { + UINT32 tag; /* + * CFR_TAG_OPTION_ENUM, CFR_TAG_OPTION_NUMBER or + * CFR_TAG_OPTION_BOOL + */ + UINT32 size; + UINT64 object_id; /* Unique ID */ + UINT64 dependency_id; /* Dependent object ID, or 0 */ + UINT32 flags; /* enum cfr_option_flags */ + UINT32 default_value; + UINT32 min; + UINT32 max; + UINT32 step; + UINT32 display_flags; /* enum cfr_numeric_option_display_flags */ + /* + * CFR_VARCHAR_OPT_NAME opt_name + * CFR_VARCHAR_UI_NAME ui_name + * CFR_VARCHAR_UI_HELPTEXT ui_helptext (Optional) + * CFR_DEP_VALUES dependency_values (Optional) + * CFR_ENUM_VALUE enum_values[] + */ +} CFR_OPTION_NUMERIC; + +#define CB_TAG_CFR_OPTION_VARCHAR 0x0006 +typedef struct { + UINT32 tag; /* CFR_OPTION_VARCHAR */ + UINT32 size; + UINT64 object_id; /* Unique ID */ + UINT64 dependency_id; /* Dependent object ID, or 0 */ + UINT32 flags; /* enum cfr_option_flags */ + /* + * CFR_OPT_NAME opt_name + * CFR_UI_NAME ui_name + * CFR_UI_HELPTEXT ui_helptext (Optional) + * CFR_DEP_VALUES dependency_values (Optional) + * CFR_VARCHAR default_value + */ +} CFR_OPTION_VARCHAR; + +/* + * A CFR option comment is roughly equivalent to a Kconfig comment. + * Option comments are *NOT* string options (see CFR_OPTION_VARCHAR + * instead) but they're considered an option for simplicity's sake. + */ +#define CB_TAG_CFR_OPTION_COMMENT 0x000b +typedef struct { + UINT32 tag; /* CFR_OPTION_COMMENT */ + UINT32 size; + UINT64 object_id; /* Unique ID */ + UINT64 dependency_id; /* Dependent object ID, or 0 */ + UINT32 flags; /* enum cfr_option_flags */ + /* + * CFR_UI_NAME ui_name + * CFR_UI_HELPTEXT ui_helptext (Optional) + * CFR_DEP_VALUES dependency_values (Optional) + */ +} CFR_OPTION_COMMENT; + +/* CFR forms are considered options as they can be nested inside other forms */ +#define CB_TAG_CFR_OPTION_FORM 0x0001 +typedef struct { + UINT32 tag; /* CFR_OPTION_FORM */ + UINT32 size; + UINT64 object_id; /* Unique ID */ + UINT64 dependency_id; /* Dependent object ID, or 0 */ + UINT32 flags; /* enum cfr_option_flags */ + /* + * CFR_UI_NAME ui_name + * CFR_DEP_VALUES dependency_values (Optional) + * options[] + */ +} CFR_OPTION_FORM; +#pragma pack () + +#endif // __CFR_SETUP_MENU_GUID_H__ diff --git a/UefiPayloadPkg/Include/Guid/TcgPhysicalPresenceGuid.h b/UefiPayloadPkg/Include/Guid/TcgPhysicalPresenceGuid.h new file mode 100644 index 000000000000..1f8ca6e3ab39 --- /dev/null +++ b/UefiPayloadPkg/Include/Guid/TcgPhysicalPresenceGuid.h @@ -0,0 +1,30 @@ +/** @file + This file defines the hob structure for Tcg Physical Presence Interface. + + Copyright (c) 2020, 9elements Agency GmbH
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __TCG_PHYSICAL_PRESENCE_GUID_H__ +#define __TCG_PHYSICAL_PRESENCE_GUID_H__ + +/// +/// TCG Physical Presence Information GUID +/// +extern EFI_GUID gEfiTcgPhysicalPresenceInfoHobGuid; + +typedef struct { + UINT32 PpiAddress; + UINT8 TpmVersion; + UINT8 PpiVersion; +} TCG_PHYSICAL_PRESENCE_INFO; + +#define UEFIPAYLOAD_TPM_VERSION_UNSPEC 0 +#define UEFIPAYLOAD_TPM_VERSION_1_2 1 +#define UEFIPAYLOAD_TPM_VERSION_2 2 + +#define UEFIPAYLOAD_TPM_PPI_VERSION_NONE 0 +#define UEFIPAYLOAD_TPM_PPI_VERSION_1_30 1 + +#endif diff --git a/UefiPayloadPkg/Include/Library/BlParseLib.h b/UefiPayloadPkg/Include/Library/BlParseLib.h index 82be5a9eb85a..db7684ffbcf7 100644 --- a/UefiPayloadPkg/Include/Library/BlParseLib.h +++ b/UefiPayloadPkg/Include/Library/BlParseLib.h @@ -17,6 +17,7 @@ #include #include #include +#include #define GET_BOOTLOADER_PARAMETER() PcdGet64 (PcdBootloaderParameter) @@ -148,4 +149,19 @@ ParseMiscInfo ( VOID ); +/** + Find the Tcg Physical Presence store information + + @param PPIInfo Pointer to the TCG_PHYSICAL_PRESENCE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseTPMPPIInfo ( + OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo + ); + #endif diff --git a/UefiPayloadPkg/Include/Library/CfrHelpersLib.h b/UefiPayloadPkg/Include/Library/CfrHelpersLib.h new file mode 100644 index 000000000000..e05268e3f2b2 --- /dev/null +++ b/UefiPayloadPkg/Include/Library/CfrHelpersLib.h @@ -0,0 +1,53 @@ +/** @file + Contains helper functions for working with CFR. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _CFR_HELPERS_LIB_H_ +#define _CFR_HELPERS_LIB_H_ + +#include +#include +#include +#include + +/** + CFR_VARBINARY records are variable-length, so they aren't formal fields. + Implement this handling by returning the struct at this offset. + + By incrementing the offset, this function behaves like a queue. + Optional fields handled by returning NULL immediately. + +**/ +CFR_VARBINARY * +EFIAPI +CfrExtractVarBinary ( + IN UINT8 *Buffer, + IN OUT UINTN *Offset, + IN UINT32 TargetTag + ); + +/** + Return pointers into a buffer with the requested option's default value and size. + This may be used by code that needs CFR defaults before the full CFR driver can write variables. + + TODO: Consider returning pools instead, caller to free. + + @retval EFI_SUCCESS The default value is found. + @retval EFI_INVALID_PARAMETER The function parameters are invalid. + @retval EFI_NOT_FOUND The option cannot be found, or type doesn't have default values. + +**/ +EFI_STATUS +EFIAPI +CfrOptionGetDefaultValue ( + IN CHAR8 *FormName OPTIONAL, + IN CHAR8 *OptionName, + IN OUT VOID **DefaultValueData, + IN OUT UINTN *DefaultValueLength OPTIONAL + ); + +#endif diff --git a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c index d7282e07b020..6e4c101599b1 100644 --- a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c +++ b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.c @@ -7,7 +7,9 @@ **/ +#include #include +#include #include #include #include @@ -17,6 +19,7 @@ #include #include #include +#include /** Convert a packed value from cbuint64 to a UINT64 value. @@ -74,6 +77,43 @@ CbCheckSum16 ( return (UINT16)((~Sum) & 0xFFFF); } +/** + Coreboot implements a CRC32 checksum which differs from the one in EDK2. This function + calculates the CRC32 checksum of a given buffer with the coreboot implementation. + + @param Buffer The pointer to the buffer of which to calculate the CRC32. + @param Length The size, in bytes, of Buffer. + + @return Crc The CRC32 checksum of Buffer. + +**/ +UINT32 +CbCalculateCrc32 ( + IN VOID *Buffer, + IN UINTN Length + ) +{ + UINT32 Crc; + UINT8 *Ptr; + UINTN Idx; + UINTN BitIdx; + + Crc = 0; + for (Idx = 0, Ptr = Buffer; Idx < Length; Idx++, Ptr++) { + Crc ^= (UINT32)*Ptr << 24; + + for (BitIdx = 0; BitIdx < 8; BitIdx++) { + if ((Crc & 0x80000000UL) != 0) { + Crc = ((Crc << 1) ^ 0x04C11DB7UL); + } else { + Crc <<= 1; + } + } + } + + return Crc; +} + /** Check the coreboot table if it is valid. @@ -583,9 +623,11 @@ ParseGfxDeviceInfo ( /** Parse and handle the misc info provided by bootloader - @retval RETURN_SUCCESS The misc information was parsed successfully. - @retval RETURN_NOT_FOUND Could not find required misc info. - @retval RETURN_OUT_OF_RESOURCES Insufficant memory space. + @retval RETURN_SUCCESS The misc information was parsed successfully. + @retval RETURN_INCOMPATIBLE_VERSION The provided CFR data does not match the expected version. + @retval RETURN_CRC_ERROR The calculated checksum does not match the supplied one. + @retval RETURN_NOT_FOUND Could not find required misc info. + @retval RETURN_OUT_OF_RESOURCES Insufficant memory space. **/ RETURN_STATUS @@ -594,6 +636,70 @@ ParseMiscInfo ( VOID ) { + struct cb_cfr *CbCfrSetupMenu; + UINT32 CfrCalculatedChecksum; + UINTN ProcessedLength; + CFR_OPTION_FORM *CbCfrOuterFormOffset; + CFR_OPTION_FORM *CfrSetupMenuForm; + CFR_VARBINARY *CfrFormName; + + // + // CFR has several CB tags, though these are nested structures, + // not for individual table-to-HOB conversion + // + CbCfrSetupMenu = FindCbTag (CB_TAG_CFR_ROOT); + if (CbCfrSetupMenu == NULL) { + DEBUG ((DEBUG_ERROR, "CFR Tag not found in cbtables\n")); + return RETURN_NOT_FOUND; + } + + if (CbCfrSetupMenu->version != CB_CFR_VERSION) { + DEBUG ((DEBUG_WARN, "CFR: version mismatch! (expected %d, got %d)\n", CB_CFR_VERSION, CbCfrSetupMenu->version)); + return RETURN_INCOMPATIBLE_VERSION; + } + + // + // Checksum over CFR_FORM[] data -- CbCfrSetupMenu header excluded + // + CfrCalculatedChecksum = CbCalculateCrc32 (CbCfrSetupMenu + 1, CbCfrSetupMenu->size - sizeof(*CbCfrSetupMenu)); + + if (CfrCalculatedChecksum != CbCfrSetupMenu->checksum) { + DEBUG ((DEBUG_WARN, "CFR: Calculated CRC32 0x%x does not match stored CRC32 0x%x!\n", CfrCalculatedChecksum, CbCfrSetupMenu->checksum)); + return RETURN_CRC_ERROR; + } + + ProcessedLength = sizeof (struct cb_cfr); + + // + // Copy each form to HOB; TODO: This creates duplicate, copy pointer? + // + while (ProcessedLength < CbCfrSetupMenu->size) { + CbCfrOuterFormOffset = (CFR_OPTION_FORM *)((UINT8 *)CbCfrSetupMenu + ProcessedLength); + if (CbCfrOuterFormOffset->tag != CB_TAG_CFR_OPTION_FORM) { + DEBUG ((DEBUG_ERROR, "CFR Tag mismatch: 0x%x vs 0x%x\n", CbCfrOuterFormOffset->tag, CB_TAG_CFR_OPTION_FORM)); + return RETURN_NOT_FOUND; + } + CfrSetupMenuForm = BuildGuidDataHob ( + &gEfiCfrSetupMenuFormGuid, + CbCfrOuterFormOffset, + CbCfrOuterFormOffset->size + ); + if (CfrSetupMenuForm == NULL) { + break; + } + ASSERT (CfrSetupMenuForm->tag == CB_TAG_CFR_OPTION_FORM); + + CfrFormName = (CFR_VARBINARY *)((UINT8 *)CfrSetupMenuForm + sizeof (CFR_OPTION_FORM)); + DEBUG (( + DEBUG_INFO, + "CFR: Found form \"%a\", size 0x%x bytes\n", + CfrFormName->data, + CfrSetupMenuForm->size + )); + + ProcessedLength += CfrSetupMenuForm->size; + } + return RETURN_SUCCESS; } @@ -627,14 +733,67 @@ ParseSmmStoreInfo ( DEBUG ((DEBUG_INFO, "number of blocks: 0x%x\n", CbSSRec->num_blocks)); DEBUG ((DEBUG_INFO, "communication buffer: 0x%x\n", CbSSRec->com_buffer)); DEBUG ((DEBUG_INFO, "communication buffer size: 0x%x\n", CbSSRec->com_buffer_size)); - DEBUG ((DEBUG_INFO, "MMIO address of store: 0x%x\n", CbSSRec->mmap_addr)); SmmStoreInfo->ComBuffer = CbSSRec->com_buffer; SmmStoreInfo->ComBufferSize = CbSSRec->com_buffer_size; SmmStoreInfo->BlockSize = CbSSRec->block_size; SmmStoreInfo->NumBlocks = CbSSRec->num_blocks; - SmmStoreInfo->MmioAddress = CbSSRec->mmap_addr; + + if (CbSSRec->size >= 40 && CbSSRec->mmap_addr_ext) { + SmmStoreInfo->MmioAddress = CbSSRec->mmap_addr_ext; + } else { + SmmStoreInfo->MmioAddress = CbSSRec->mmap_addr; + } + + DEBUG ((DEBUG_INFO, "MMIO address of store: 0x%llx\n", SmmStoreInfo->MmioAddress)); + SmmStoreInfo->ApmCmd = CbSSRec->apm_cmd; return RETURN_SUCCESS; } + +/** + Find the Tcg Physical Presence store information + @param PPIInfo Pointer to the TCG_PHYSICAL_PRESENCE_INFO structure + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . +**/ +RETURN_STATUS +EFIAPI +ParseTPMPPIInfo ( + OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo + ) +{ + struct cb_tpm_physical_presence *CbTPPRec; + UINT8 VersionMajor; + UINT8 VersionMinor; + + if (PPIInfo == NULL) { + return RETURN_INVALID_PARAMETER; + } + + CbTPPRec = FindCbTag (CB_TAG_TPM_PPI_HANDOFF); + if (CbTPPRec == NULL) { + return RETURN_NOT_FOUND; + } + + VersionMajor = CbTPPRec->ppi_version >> 4; + VersionMinor = CbTPPRec->ppi_version & 0xF; + + DEBUG ((DEBUG_INFO, "Found Tcg Physical Presence information\n")); + DEBUG ((DEBUG_INFO, "PpiAddress: 0x%x\n", CbTPPRec->ppi_address)); + DEBUG ((DEBUG_INFO, "TpmVersion: 0x%x\n", CbTPPRec->tpm_version)); + DEBUG ((DEBUG_INFO, "PpiVersion: %x.%x\n", VersionMajor, VersionMinor)); + + PPIInfo->PpiAddress = CbTPPRec->ppi_address; + if (CbTPPRec->tpm_version == LB_TPM_VERSION_TPM_VERSION_1_2) { + PPIInfo->TpmVersion = UEFIPAYLOAD_TPM_VERSION_1_2; + } else if (CbTPPRec->tpm_version == LB_TPM_VERSION_TPM_VERSION_2) { + PPIInfo->TpmVersion = UEFIPAYLOAD_TPM_VERSION_2; + } + if (VersionMajor == 1 && VersionMinor >= 3) { + PPIInfo->PpiVersion = UEFIPAYLOAD_TPM_PPI_VERSION_1_30; + } + + return RETURN_SUCCESS; +} diff --git a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf index cf81697703cc..7924d77c3ba2 100644 --- a/UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf +++ b/UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf @@ -34,6 +34,10 @@ IoLib DebugLib PcdLib + HobLib + +[Guids] + gEfiCfrSetupMenuFormGuid [Pcd] gUefiPayloadPkgTokenSpaceGuid.PcdBootloaderParameter diff --git a/UefiPayloadPkg/Library/CfrHelpersLib/CfrHelpersLib.c b/UefiPayloadPkg/Library/CfrHelpersLib/CfrHelpersLib.c new file mode 100644 index 000000000000..f8f427180857 --- /dev/null +++ b/UefiPayloadPkg/Library/CfrHelpersLib/CfrHelpersLib.c @@ -0,0 +1,170 @@ +/** @file + Contains helper functions for working with CFR. + + Copyright (c) 2023, 9elements GmbH.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + CFR_VARBINARY records are variable-length, so they aren't formal fields. + Implement this handling by returning the struct at this offset. + + By incrementing the offset, this function behaves like a queue. + Optional fields handled by returning NULL immediately. + +**/ +CFR_VARBINARY * +EFIAPI +CfrExtractVarBinary ( + IN UINT8 *Buffer, + IN OUT UINTN *Offset, + IN UINT32 TargetTag + ) +{ + CFR_VARBINARY *CfrVarBinary; + + CfrVarBinary = (CFR_VARBINARY *)(Buffer + *Offset); + if (CfrVarBinary->tag != TargetTag) { + return NULL; + } + + *Offset += CfrVarBinary->size; + + return CfrVarBinary; +} + +/** + Return pointers into a buffer with the requested option's default value and size. + This may be used by code that needs CFR defaults before the full CFR driver can write variables. + + TODO: Consider returning pools instead, caller to free. + + @retval EFI_SUCCESS The default value is found. + @retval EFI_INVALID_PARAMETER The function parameters are invalid. + @retval EFI_NOT_FOUND The option cannot be found, or type doesn't have default values. + +**/ +EFI_STATUS +EFIAPI +CfrOptionGetDefaultValue ( + IN CHAR8 *FormName OPTIONAL, + IN CHAR8 *OptionName, + IN OUT VOID **DefaultValueData, + IN OUT UINTN *DefaultValueLength OPTIONAL + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + CFR_OPTION_FORM *CfrFormHob; + UINTN ProcessedLength; + UINTN OptionProcessedLength; + CFR_VARBINARY *CfrFormName; + CFR_OPTION_FORM *CfrFormData; + CFR_VARBINARY *CfrOptionName; + CFR_VARBINARY *TempUiName; + CFR_VARBINARY *TempHelpText; + CFR_VARBINARY *CfrDefaultValue; + + if ((OptionName == NULL) || (DefaultValueData == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Begin processing a form HOB + // + GuidHob = GetFirstGuidHob (&gEfiCfrSetupMenuFormGuid); + while (GuidHob != NULL) { + CfrFormHob = GET_GUID_HOB_DATA (GuidHob); + + ProcessedLength = sizeof (CFR_OPTION_FORM); + CfrFormName = CfrExtractVarBinary ((UINT8 *)CfrFormHob, &ProcessedLength, CB_TAG_CFR_VARCHAR_UI_NAME); + ASSERT (CfrFormName != NULL); + + // + // Different form requested, skip this + // + if ((FormName != NULL) && (AsciiStrCmp (FormName, (CHAR8 *)CfrFormName->data) != 0)) { + GuidHob = GetNextGuidHob (&gEfiCfrSetupMenuFormGuid, GET_NEXT_HOB (GuidHob)); + continue; + } + + // + // Process form tree + // + while (ProcessedLength < CfrFormHob->size) { + CfrFormData = (CFR_OPTION_FORM *)((UINT8 *)CfrFormHob + ProcessedLength); + + switch (CfrFormData->tag) { + case CB_TAG_CFR_OPTION_FORM: + // Processing nested forms, don't advance by `size` + ProcessedLength += sizeof (CFR_OPTION_FORM); + CfrFormName = CfrExtractVarBinary ((UINT8 *)CfrFormHob, &ProcessedLength, CB_TAG_CFR_VARCHAR_UI_NAME); + ASSERT (CfrFormName != NULL); + + // Forms do not have default values + if (AsciiStrCmp (OptionName, (CHAR8 *)CfrFormName->data) == 0) { + return EFI_NOT_FOUND; + } + break; + case CB_TAG_CFR_OPTION_ENUM: + case CB_TAG_CFR_OPTION_NUMBER: + case CB_TAG_CFR_OPTION_BOOL: + OptionProcessedLength = sizeof (CFR_OPTION_NUMERIC); + CfrOptionName = CfrExtractVarBinary ((UINT8 *)CfrFormData, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_OPT_NAME); + ASSERT (CfrOptionName != NULL); + + if (AsciiStrCmp (OptionName, (CHAR8 *)CfrOptionName->data) == 0) { + *DefaultValueData = &((CFR_OPTION_NUMERIC *)CfrFormData)->default_value; + if (DefaultValueLength != NULL) { + *DefaultValueLength = sizeof (((CFR_OPTION_NUMERIC *)CfrFormData)->default_value); + } + return EFI_SUCCESS; + } + ProcessedLength += CfrFormData->size; + break; + case CB_TAG_CFR_OPTION_VARCHAR: + // Currently required to remove intermediate VARBINARY structs of UI data + OptionProcessedLength = sizeof (CFR_OPTION_VARCHAR); + CfrOptionName = CfrExtractVarBinary ((UINT8 *)CfrFormData, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_OPT_NAME); + ASSERT (CfrOptionName != NULL); + + TempUiName = CfrExtractVarBinary ((UINT8 *)CfrFormData, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_UI_NAME); + ASSERT (TempUiName != NULL); + TempHelpText = CfrExtractVarBinary ((UINT8 *)CfrFormData, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_UI_HELPTEXT); + if (TempHelpText != NULL) { + ASSERT (TempHelpText->tag == CB_TAG_CFR_VARCHAR_UI_HELPTEXT); + } + + CfrDefaultValue = CfrExtractVarBinary ((UINT8 *)CfrFormData, &OptionProcessedLength, CB_TAG_CFR_VARCHAR_DEF_VALUE); + ASSERT (CfrDefaultValue != NULL); + + if (AsciiStrCmp (OptionName, (CHAR8 *)CfrOptionName->data) == 0) { + *DefaultValueData = CfrDefaultValue->data; + if (DefaultValueLength != NULL) { + *DefaultValueLength = CfrDefaultValue->data_length; + } + return EFI_SUCCESS; + } + ProcessedLength += CfrFormData->size; + break; + case CB_TAG_CFR_OPTION_COMMENT: + default: + ProcessedLength += CfrFormData->size; + break; + } + } + + GuidHob = GetNextGuidHob (&gEfiCfrSetupMenuFormGuid, GET_NEXT_HOB (GuidHob)); + } + + return EFI_NOT_FOUND; +} diff --git a/UefiPayloadPkg/Library/CfrHelpersLib/CfrHelpersLib.inf b/UefiPayloadPkg/Library/CfrHelpersLib/CfrHelpersLib.inf new file mode 100644 index 000000000000..dce88b4cf09d --- /dev/null +++ b/UefiPayloadPkg/Library/CfrHelpersLib/CfrHelpersLib.inf @@ -0,0 +1,30 @@ +## @file +# Contains helper functions for working with CFR. +# +# Copyright (c) 2023, 9elements GmbH.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CfrHelpersLib + FILE_GUID = 4165BB9B-54BF-40B7-AD56-D51D1D90FFB7 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CfrHelpersLib + +[Sources] + CfrHelpersLib.c + +[Packages] + MdePkg/MdePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + HobLib + +[Guids] + gEfiCfrSetupMenuFormGuid diff --git a/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf index 6069dcc0efa3..5b19a8a0e89e 100644 --- a/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf +++ b/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf @@ -39,6 +39,7 @@ DevicePathLib MemoryAllocationLib PciLib + DxeServicesTableLib [Guids] gUniversalPayloadPciRootBridgeInfoGuid diff --git a/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c b/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c index fb76853072ea..ba04ba360bee 100644 --- a/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c +++ b/UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "PciHostBridge.h" /** @@ -53,6 +54,55 @@ PcatPciRootBridgeBarExisted ( EnableInterrupts (); } +STATIC +EFI_STATUS +PcatPciRootBridgeWarnAboutBrokenFW ( + IN UINT64 Start, + IN UINT64 Limit +) +{ + EFI_STATUS Status; + UINTN Index; + UINT64 IntersectionBase; + UINT64 IntersectionEnd; + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Map; + + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &Map); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n", + gEfiCallerBaseName, __FUNCTION__, Status)); + return Status; + } + + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if (Map[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) { + // + // Ignore non existent entries + // + continue; + } + + IntersectionBase = MAX (Start, Map[Index].BaseAddress); + IntersectionEnd = MIN (Limit, Map[Index].BaseAddress + Map[Index].Length); + if (IntersectionBase >= IntersectionEnd) { + // + // The descriptor and the aperture don't overlap. + // + continue; + } + + if (Map[Index].GcdMemoryType == EfiGcdMemoryTypeReserved) { + DEBUG ((EFI_D_ERROR, "%a: PCI aperature overlaps reserved memory region\n", + __FUNCTION__)); + DEBUG ((EFI_D_ERROR, "%a: Please consider fixing EDK2 or your firmware\n", + __FUNCTION__)); + return EFI_ACCESS_DENIED; + } + } + return EFI_SUCCESS; +} + /** Parse PCI bar and collect the assigned PCI resource information. @@ -104,6 +154,9 @@ PcatPciRootBridgeParseBars ( UINT64 Length; UINT64 Limit; PCI_ROOT_BRIDGE_APERTURE *MemAperture; + UINT64 NewBase; + UINT64 NewLength; + EFI_STATUS Status; for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) { PcatPciRootBridgeBarExisted ( @@ -182,6 +235,33 @@ PcatPciRootBridgeParseBars ( Limit = Base + Length - 1; if ((Base > 0) && (Base < Limit)) { + NewBase = MemAperture->Base; + if (MemAperture->Base > Base) { + NewBase = Base; + } + NewLength = MemAperture->Base; + if (MemAperture->Limit < Limit) { + NewLength = Base; + } + + // + // In case the BAR is placed on "the other side" of the MMCONF window + // this would cause the aperature to cover the MMCONF window, which + // isn't supported by EDK2. + // + Status = PcatPciRootBridgeWarnAboutBrokenFW(NewBase, NewLength); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: Not adding PCI %x:%x.%x BAR@%d %x:%x to aperature\n", + __FUNCTION__, + Bus, + Device, + Function, + Offset, + Base, + Limit)); + continue; + } + if (MemAperture->Base > Base) { MemAperture->Base = Base; } diff --git a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c index a4a49da0e9c5..310b22b1b4bc 100644 --- a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c +++ b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c @@ -212,6 +212,108 @@ PlatformRegisterFvBootOption ( } } +EFI_HANDLE BootManagerEntryNotifyHandle1; +EFI_HANDLE BootManagerEntryNotifyHandle2; + +VOID +PlatformUnregisterBootManagerEntryNotifyCallback ( + VOID + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx; + + Status = gBS->LocateProtocol ( + &gEfiSimpleTextInputExProtocolGuid, + NULL, + (VOID **)&SimpleEx + ); + if (!EFI_ERROR (Status)) { + Status = SimpleEx->UnregisterKeyNotify (SimpleEx, BootManagerEntryNotifyHandle1); + Status = SimpleEx->UnregisterKeyNotify (SimpleEx, BootManagerEntryNotifyHandle2); + } +} + +EFI_STATUS +EFIAPI +BootManagerEntryNotifyCallback ( + EFI_KEY_DATA *KeyData + ) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL White; + + // + // We can't call UnregisterKeyNotify () from this handler, + // so work around it by only updating the progress message once + // + static UINTN UpdateProgressMessage = 1; + + Black.Blue = Black.Green = Black.Red = Black.Reserved = 0; + White.Blue = White.Green = White.Red = White.Reserved = 0xFF; + + if (UpdateProgressMessage) { + BootLogoUpdateProgress ( + White, + Black, + L"Entering Setup, Please Wait...", + White, + 0, + 0 + ); + UpdateProgressMessage = 0; + } + + return EFI_SUCCESS; +} + +VOID +PlatformRegisterBootManagerEntryNotifyCallback ( + VOID + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx; + EFI_KEY_DATA KeyData; + + Status = gBS->LocateProtocol ( + &gEfiSimpleTextInputExProtocolGuid, + NULL, + (VOID **)&SimpleEx + ); + if (EFI_ERROR (Status)) { + return; + } + + KeyData.Key.UnicodeChar = CHAR_NULL; + KeyData.KeyState.KeyShiftState = 0; + KeyData.KeyState.KeyToggleState = 0; + + if (FixedPcdGetBool (PcdBootManagerEscape)) { + KeyData.Key.ScanCode = SCAN_ESC; + } else { + KeyData.Key.ScanCode = SCAN_F2; + } + + Status = SimpleEx->RegisterKeyNotify ( + SimpleEx, + &KeyData, + BootManagerEntryNotifyCallback, + &BootManagerEntryNotifyHandle1 + ); + + KeyData.Key.ScanCode = SCAN_DOWN; + + if (!EFI_ERROR (Status)) { + Status = SimpleEx->RegisterKeyNotify ( + SimpleEx, + &KeyData, + BootManagerEntryNotifyCallback, + &BootManagerEntryNotifyHandle2 + ); + } +} + /** Do the platform specific action before the console is connected. @@ -263,6 +365,11 @@ PlatformBootManagerBeforeConsole ( EfiBootManagerGetBootManagerMenu (&BootOption); EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &Down, NULL); + // + // Register a callback to show a message when the Boot Manager Menu hotkey is pressed. + // + PlatformRegisterBootManagerEntryNotifyCallback (); + // // Install ready to lock. // This needs to be done before option rom dispatched. @@ -311,26 +418,41 @@ PlatformBootManagerAfterConsole ( EfiBootManagerConnectAll (); EfiBootManagerRefreshAllBootOption (); + // + // Process TPM PPI request + // + Status=TcgPhysicalPresenceLibProcessRequest (); // Check for TPM1.2 First + if (EFI_ERROR (Status)) { + Tcg2PhysicalPresenceLibProcessRequest (NULL); //Check for TPM2.0 + } + // // Register UEFI Shell // PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE); if (FixedPcdGetBool (PcdBootManagerEscape)) { - Print ( - L"\n" - L" Esc or Down to enter Boot Manager Menu.\n" - L" ENTER to boot directly.\n" - L"\n" + BootLogoUpdateProgress ( + White, + Black, + L"Press ESC for Boot Options/Settings", + White, + 0, + 0 ); } else { - Print ( - L"\n" - L" F2 or Down to enter Boot Manager Menu.\n" - L" ENTER to boot directly.\n" - L"\n" + BootLogoUpdateProgress ( + White, + Black, + L"Press F2 or Down for Boot Options/Settings", + White, + 0, + 0 ); } + + // invoke SMM handler to put BYT eMMC/SD devices into ACPI mode for OS + IoWrite8(0xb2, 0xcd); } /** @@ -344,6 +466,11 @@ PlatformBootManagerWaitCallback ( UINT16 TimeoutRemain ) { + if (TimeoutRemain == 0) { + BootLogoClearProgress (); + PlatformUnregisterBootManagerEntryNotifyCallback (); + } + return; } diff --git a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h index 2110997d9bbc..8a16b8765964 100644 --- a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h +++ b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h @@ -26,6 +26,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include +#include +#include #include typedef struct { diff --git a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index 987c73040e58..7b94cae44f0b 100644 --- a/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -32,6 +32,7 @@ MdeModulePkg/MdeModulePkg.dec UefiPayloadPkg/UefiPayloadPkg.dec ShellPkg/ShellPkg.dec + SecurityPkg/SecurityPkg.dec [LibraryClasses] BaseLib @@ -47,6 +48,9 @@ HiiLib PrintLib PlatformHookLib + IoLib + TcgPhysicalPresenceLib + Tcg2PhysicalPresenceLib [Guids] gEfiEndOfDxeEventGroupGuid diff --git a/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c b/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c index de139a5305ad..60bb361e76a6 100644 --- a/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c +++ b/UefiPayloadPkg/Library/SblParseLib/SblParseLib.c @@ -307,3 +307,18 @@ ParseSmmStoreInfo ( { return RETURN_NOT_FOUND; } + +/** + Find the Tcg Physical Presence store information + @param PPIInfo Pointer to the TCG_PHYSICAL_PRESENCE_INFO structure + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . +**/ +RETURN_STATUS +EFIAPI +ParseTPMPPIInfo ( + OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo + ) +{ + return RETURN_NOT_FOUND; +} diff --git a/UefiPayloadPkg/Library/SmmStoreLib/SmmStore.c b/UefiPayloadPkg/Library/SmmStoreLib/SmmStore.c index 690bae0f1cf1..6b3783d5d789 100644 --- a/UefiPayloadPkg/Library/SmmStoreLib/SmmStore.c +++ b/UefiPayloadPkg/Library/SmmStoreLib/SmmStore.c @@ -393,7 +393,7 @@ SmmStoreLibInitialize ( // Mark the memory mapped store as MMIO memory // Status = gDS->GetMemorySpaceDescriptor (mSmmStoreInfo->MmioAddress, &GcdDescriptor); - if (EFI_ERROR (Status) || (GcdDescriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo)) { + if (EFI_ERROR (Status)) { DEBUG (( DEBUG_INFO, "%a: No memory space descriptor for com buffer found\n", @@ -410,18 +410,32 @@ SmmStoreLibInitialize ( EFI_MEMORY_UC | EFI_MEMORY_RUNTIME ); ASSERT_EFI_ERROR (Status); + } else { + Status = gDS->SetMemorySpaceCapabilities ( + mSmmStoreInfo->MmioAddress, + mSmmStoreInfo->NumBlocks * mSmmStoreInfo->BlockSize, + GcdDescriptor.Capabilities | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceCapabilities failed\n", __func__, __LINE__)); + return Status; + } + // + // Mark as runtime service + // + Status = gDS->SetMemorySpaceAttributes ( + mSmmStoreInfo->MmioAddress, + mSmmStoreInfo->NumBlocks * mSmmStoreInfo->BlockSize, + GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __func__, __LINE__)); + return Status; + } } - // - // Mark as runtime service - // - Status = gDS->SetMemorySpaceAttributes ( - mSmmStoreInfo->MmioAddress, - mSmmStoreInfo->NumBlocks * mSmmStoreInfo->BlockSize, - EFI_MEMORY_RUNTIME - ); - ASSERT_EFI_ERROR (Status); - return EFI_SUCCESS; } diff --git a/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresenceLib.c b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresenceLib.c new file mode 100644 index 000000000000..a3871503d677 --- /dev/null +++ b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresenceLib.c @@ -0,0 +1,965 @@ +/** @file + Execute pending TPM2 requests from OS or BIOS. + + Caution: This module requires additional review when modified. + This driver will have external input - variable. + This external input must be validated carefully to avoid security issue. + + Tcg2ExecutePendingTpmRequest() will receive untrusted input and do validation. + +Copyright (C) 2018, Red Hat, Inc. +Copyright (c) 2018, IBM Corporation. All rights reserved.
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define CONFIRM_BUFFER_SIZE 4096 + +EFI_HII_HANDLE mTcg2PpStringPackHandle; + +/* Wait 3 minutes for user input */ +#define TIMEOUT (1000 * 1000 * 60 * 3) + +#define TPM_PPI_FLAGS (QEMU_TPM_PPI_FUNC_ALLOWED_USR_REQ) + +STATIC volatile QEMU_TPM_PPI *mPpi; + +#define CACHELINE_SIZE 64 + +/** + Add Function to flush cached PPI data to memory + Need to Flush cache to RAM otherwise mPpi are not stored ... + + @param[in] FLUSH_ALL_CACHE Flush whole Cache. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR PPI address is invalid or Len is invalid. +**/ +EFI_STATUS +Flush_PPI_Cache ( + BOOLEAN FLUSH_ALL_CACHE + ) +{ + EFI_PHYSICAL_ADDRESS Ppi_address = (UINTN)mPpi; + UINTN Param_Len = (sizeof(QEMU_TPM_PPI) -1) | (CACHELINE_SIZE-1); + + if (( Ppi_address == (UINTN)NULL) || (Param_Len <=0)) return EFI_PROTOCOL_ERROR; + + DEBUG ((DEBUG_INFO, "[TPM2PP] Address=%p Len=%X\n", Ppi_address, Param_Len)); + + switch (FLUSH_ALL_CACHE) + { + case 0: //Flush Only mPPI struct + for (EFI_PHYSICAL_ADDRESS Flush=Ppi_address; Flush <= Ppi_address+Param_Len; Flush+=CACHELINE_SIZE) { + AsmFlushCacheLine((char*)Flush); + //DEBUG ((DEBUG_INFO, "[TPM2PP] Flush cache addr=%p\n", Flush)); + } + break; + case 1: + default: + AsmWbinvd (); //Flush All cache + //DEBUG ((DEBUG_INFO, "[TPM2PP] Flush whole cache\n")); + break; + } + + return EFI_SUCCESS; +} + + +/** + Initializes QEMU PPI memory region. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR PPI address is invalid. +**/ +STATIC +EFI_STATUS +QemuTpmInitPPI ( + VOID + ) +{ + EFI_STATUS Status; + QEMU_FWCFG_TPM_CONFIG Config; + BOOLEAN PPIinMMIO; + EFI_PHYSICAL_ADDRESS PpiAddress64; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINTN Idx; + + if (mPpi != NULL) { + return EFI_SUCCESS; + } + + Status = TpmPPIPlatformReadConfig (&Config, &PPIinMMIO); + if (EFI_ERROR (Status)) { + return Status; + } + + mPpi = (QEMU_TPM_PPI *)(UINTN)Config.PpiAddress; + if (mPpi == NULL) { + return EFI_PROTOCOL_ERROR; + } + + DEBUG ((DEBUG_INFO, "[TPM2PP] mPpi=%p version=%d\n", mPpi, Config.TpmVersion)); + + PpiAddress64 = (UINTN)mPpi; + if ((PpiAddress64 & ~(UINT64)EFI_PAGE_MASK) != + ((PpiAddress64 + sizeof *mPpi - 1) & ~(UINT64)EFI_PAGE_MASK)) + { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi crosses a page boundary\n")); + goto InvalidPpiAddress; + } + + Status = gDS->GetMemorySpaceDescriptor (PpiAddress64, &Descriptor); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto InvalidPpiAddress; + } + + if (PPIinMMIO) { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent)) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } + } else { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } + } + + for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) { + mPpi->Func[Idx] = 0; + } + + if (Config.TpmVersion == QEMU_TPM_VERSION_2) { + mPpi->Func[TCG2_PHYSICAL_PRESENCE_NO_ACTION] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_CLEAR] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_CHANGE_EPS] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID] = TPM_PPI_FLAGS; + mPpi->Func[TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID] = TPM_PPI_FLAGS; + } + + if (mPpi->In == 0) { + mPpi->In = 1; + mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->LastRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->NextStep = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + } + + return EFI_SUCCESS; + +InvalidPpiAddress: + mPpi = NULL; + return EFI_PROTOCOL_ERROR; +} + +/** + Get string by string id from HII Interface. + + @param[in] Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +STATIC +CHAR16 * +Tcg2PhysicalPresenceGetStringById ( + IN EFI_STRING_ID Id + ) +{ + return HiiGetString (mTcg2PpStringPackHandle, Id, NULL); +} + +/** + Send ClearControl and Clear command to TPM. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_TIMEOUT The register can't run into the expected status in time. + @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small. + @retval EFI_DEVICE_ERROR Unexpected device behavior. + +**/ +EFI_STATUS +EFIAPI +Tpm2CommandClear ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + EFI_STATUS Status; + TPMS_AUTH_COMMAND *AuthSession; + TPMS_AUTH_COMMAND LocalAuthSession; + + if (PlatformAuth == NULL) { + AuthSession = NULL; + } else { + AuthSession = &LocalAuthSession; + ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession)); + LocalAuthSession.sessionHandle = TPM_RS_PW; + LocalAuthSession.hmac.size = PlatformAuth->size; + CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size); + } + + DEBUG ((DEBUG_INFO, "Tpm2ClearControl ... \n")); + Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO); + DEBUG ((DEBUG_INFO, "Tpm2ClearControl - %r\n", Status)); + if (EFI_ERROR (Status)) { + goto Done; + } + + DEBUG ((DEBUG_INFO, "Tpm2Clear ... \n")); + Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession); + DEBUG ((DEBUG_INFO, "Tpm2Clear - %r\n", Status)); + +Done: + ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac)); + return Status; +} + +/** + Change EPS. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + + @retval EFI_SUCCESS Operation completed successfully. +**/ +STATIC +EFI_STATUS +Tpm2CommandChangeEps ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + EFI_STATUS Status; + TPMS_AUTH_COMMAND *AuthSession; + TPMS_AUTH_COMMAND LocalAuthSession; + + if (PlatformAuth == NULL) { + AuthSession = NULL; + } else { + AuthSession = &LocalAuthSession; + ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession)); + LocalAuthSession.sessionHandle = TPM_RS_PW; + LocalAuthSession.hmac.size = PlatformAuth->size; + CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size); + } + + Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession); + DEBUG ((DEBUG_INFO, "Tpm2ChangeEPS - %r\n", Status)); + + ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac)); + return Status; +} + +/** + Execute physical presence operation requested by the OS. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. + @param[in] CommandCode Physical presence operation value. + @param[in] CommandParameter Physical presence operation parameter. + + @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Unknown physical presence operation. + @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or + receiving response from TPM. + @retval Others Return code from the TPM device after command execution. +**/ +STATIC +UINT32 +Tcg2ExecutePhysicalPresence ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL, + IN UINT32 CommandCode, + IN UINT32 CommandParameter + ) +{ + EFI_STATUS Status; + EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap; + UINT32 ActivePcrBanks; + + switch (CommandCode) { + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + Status = Tpm2CommandClear (PlatformAuth); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks); + ASSERT_EFI_ERROR (Status); + + // + // PP spec requirements: + // Firmware should check that all requested (set) hashing algorithms are supported with respective PCR banks. + // Firmware has to ensure that at least one PCR banks is active. + // If not, an error is returned and no action is taken. + // + if ((CommandParameter == 0) || ((CommandParameter & (~TpmHashAlgorithmBitmap)) != 0)) { + DEBUG ((DEBUG_ERROR, "PCR banks %x to allocate are not supported by TPM. Skip operation\n", CommandParameter)); + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + + Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, CommandParameter); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + Status = Tpm2CommandChangeEps (PlatformAuth); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS: + Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks); + ASSERT_EFI_ERROR (Status); + Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, TpmHashAlgorithmBitmap); + if (EFI_ERROR (Status)) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } else { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } + + default: + if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { + return TCG_PP_OPERATION_RESPONSE_SUCCESS; + } else { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + } +} + +/** + Read the specified key for user confirmation. + + @param[in] CautionKey If true, F12 is used as confirm key; + If false, F10 is used as confirm key. + + @retval TRUE User confirmed the changes by input. + @retval FALSE User discarded the changes. +**/ +STATIC +BOOLEAN +Tcg2ReadUserKey ( + IN BOOLEAN CautionKey, + IN UINTN Timeout + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINT16 InputKey; + UINTN Delay; + + Delay = Timeout / 50; + + InputKey = 0; + do { + Status = gBS->CheckEvent (gST->ConIn->WaitForKey); + if (!EFI_ERROR (Status)) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (Key.ScanCode == SCAN_ESC) { + InputKey = Key.ScanCode; + } + + if ((Key.ScanCode == SCAN_F10) && !CautionKey) { + InputKey = Key.ScanCode; + } + + if ((Key.ScanCode == SCAN_F12) && CautionKey) { + InputKey = Key.ScanCode; + } + } + gBS->Stall (50); + Delay--; + } while (InputKey == 0 && Delay > 0); + + if (Delay == 0) { + return FALSE; + } + + if (InputKey != SCAN_ESC) { + return TRUE; + } + + return FALSE; +} + +/** + Fill Buffer With BootHashAlg. + + @param[in] Buffer Buffer to be filled. + @param[in] BufferSize Size of buffer. + @param[in] BootHashAlg BootHashAlg. + +**/ +STATIC +VOID +Tcg2FillBufferWithBootHashAlg ( + IN UINT16 *Buffer, + IN UINTN BufferSize, + IN UINT32 BootHashAlg + ) +{ + Buffer[0] = 0; + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { + if (Buffer[0] != 0) { + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } + + StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1); + } +} + +/** + Display the confirm text and get user confirmation. + + @param[in] TpmPpCommand The requested TPM physical presence command. + @param[in] TpmPpCommandParameter The requested TPM physical presence command parameter. + + @retval TRUE The user has confirmed the changes. + @retval FALSE The user doesn't confirm the changes. +**/ +STATIC +BOOLEAN +Tcg2UserConfirm ( + IN UINT32 TpmPpCommand, + IN UINT32 TpmPpCommandParameter + ) +{ + CHAR16 *ConfirmText; + CHAR16 *TmpStr1; + CHAR16 *TmpStr2; + UINTN BufSize; + BOOLEAN CautionKey; + BOOLEAN NoPpiInfo; + UINT16 Index; + CHAR16 DstStr[81]; + CHAR16 TempBuffer[1024]; + CHAR16 TempBuffer2[1024]; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability; + UINT32 CurrentPCRBanks; + EFI_STATUS Status; + + TmpStr2 = NULL; + CautionKey = FALSE; + NoPpiInfo = FALSE; + BufSize = CONFIRM_BUFFER_SIZE; + ConfirmText = AllocateZeroPool (BufSize); + ASSERT (ConfirmText != NULL); + + mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, Tcg2PhysicalPresenceLibQemuStrings, NULL); + ASSERT (mTcg2PpStringPackHandle != NULL); + + switch (TpmPpCommand) { + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + CautionKey = TRUE; + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + break; + + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol); + ASSERT_EFI_ERROR (Status); + + ProtocolCapability.Size = sizeof (ProtocolCapability); + Status = Tcg2Protocol->GetCapability ( + Tcg2Protocol, + &ProtocolCapability + ); + ASSERT_EFI_ERROR (Status); + + Status = Tcg2Protocol->GetActivePcrBanks ( + Tcg2Protocol, + &CurrentPCRBanks + ); + ASSERT_EFI_ERROR (Status); + + CautionKey = TRUE; + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof (TempBuffer), TpmPpCommandParameter); + Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof (TempBuffer2), CurrentPCRBanks); + + TmpStr1 = AllocateZeroPool (BufSize); + ASSERT (TmpStr1 != NULL); + UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer); + + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + break; + + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + CautionKey = TRUE; + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + break; + + case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ENABLE_BLOCK_SID)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + break; + + case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: + TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_DISABLE_BLOCK_SID)); + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + break; + + default: + ; + } + + if (TmpStr2 == NULL) { + FreePool (ConfirmText); + return FALSE; + } + + // Console for user interaction + // We need to connect all trusted consoles for TCG PP. Here we treat all consoles in OVMF to be trusted consoles. + EfiBootManagerConnectAllDefaultConsoles (); + + if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) { + if (CautionKey) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY)); + } else { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + } + + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + if (NoPpiInfo) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + } + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY)); + } else { + if (CautionKey) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY)); + } else { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY)); + } + + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + if (NoPpiInfo) { + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + } + + TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY)); + } + + BufSize -= StrSize (ConfirmText); + UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2); + + DstStr[80] = L'\0'; + for (Index = 0; Index < StrLen (ConfirmText); Index += 80) { + StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1); + Print (DstStr); + } + + FreePool (TmpStr1); + FreePool (TmpStr2); + FreePool (ConfirmText); + HiiRemovePackages (mTcg2PpStringPackHandle); + + if (Tcg2ReadUserKey (CautionKey, TIMEOUT)) { + return TRUE; + } + + return FALSE; +} + +/** + Check if there is a valid physical presence command request. Also updates parameter value + to whether the requested physical presence command already confirmed by user + + @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI. + True, it indicates the command doesn't require user confirm, or already confirmed + in last boot cycle by user. + False, it indicates the command need user confirm from UI. + + @retval TRUE Physical Presence operation command is valid. + @retval FALSE Physical Presence operation command is invalid. + +**/ +STATIC +BOOLEAN +Tcg2HaveValidTpmRequest ( + OUT BOOLEAN *RequestConfirmed + ) +{ + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_STATUS Status; + + *RequestConfirmed = FALSE; + + if (mPpi->Request <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { + // + // Need TCG2 protocol. + // + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol); + if (EFI_ERROR (Status)) { + return FALSE; + } + } + + switch (mPpi->Request) { + case TCG2_PHYSICAL_PRESENCE_NO_ACTION: + case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS: + *RequestConfirmed = TRUE; + return TRUE; + + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: + case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: + break; + + default: + // + // Wrong Physical Presence command + // + return FALSE; + } + + // + // Physical Presence command is correct + // + return TRUE; +} + +/** + Check and execute the requested physical presence command. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. +**/ +STATIC +VOID +Tcg2ExecutePendingTpmRequest ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + BOOLEAN RequestConfirmed; + + if (mPpi->Request == TCG2_PHYSICAL_PRESENCE_NO_ACTION) { + // + // No operation request + // + return; + } + + if (!Tcg2HaveValidTpmRequest (&RequestConfirmed)) { + // + // Invalid operation request. + // + if (mPpi->Request <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) { + mPpi->Response = TCG_PP_OPERATION_RESPONSE_SUCCESS; + } else { + mPpi->Response = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + + mPpi->LastRequest = mPpi->Request; + mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->RequestParameter = 0; + return; + } + + if (!RequestConfirmed) { + // + // Print confirm text and wait for approval. + // + RequestConfirmed = Tcg2UserConfirm (mPpi->Request, mPpi->RequestParameter); + } + + // + // Execute requested physical presence command + // + mPpi->Response = TCG_PP_OPERATION_RESPONSE_USER_ABORT; + if (RequestConfirmed) { + mPpi->Response = Tcg2ExecutePhysicalPresence ( + PlatformAuth, + mPpi->Request, + mPpi->RequestParameter + ); + } + + // + // Clear request + // + mPpi->LastRequest = mPpi->Request; + mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->RequestParameter = 0; + + if (mPpi->Response == TCG_PP_OPERATION_RESPONSE_USER_ABORT) { + return; + } + + // + // Reset system to make new TPM settings in effect + // + switch (mPpi->LastRequest) { + case TCG2_PHYSICAL_PRESENCE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2: + case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3: + case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS: + case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS: + case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS: + break; + + case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID: + case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID: + break; + + default: + if (mPpi->Request != TCG2_PHYSICAL_PRESENCE_NO_ACTION) { + break; + } + + return; + } + + Print (L"Rebooting system to make TPM2 settings in effect\n"); + + Flush_PPI_Cache(TRUE); //Need to Flush cache to RAM otherwise mPpi are not stored in RAM. + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + ASSERT (FALSE); +} + +/** + Check and execute the pending TPM request. + + The TPM request may come from OS or BIOS. This API will display request information and wait + for user confirmation if TPM request exists. The TPM request will be sent to TPM device after + the TPM request is confirmed, and one or more reset may be required to make TPM request to + take effect. + + This API should be invoked after console in and console out are all ready as they are required + to display request information and get user input to confirm the request. + + @param[in] PlatformAuth platform auth value. NULL means no platform auth change. +**/ +VOID +EFIAPI +Tcg2PhysicalPresenceLibProcessRequest ( + IN TPM2B_AUTH *PlatformAuth OPTIONAL + ) +{ + EFI_STATUS Status; + + Status = QemuTpmInitPPI (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n")); + return; + } + + // + // Check S4 resume + // + if (GetBootModeHob () == BOOT_ON_S4_RESUME) { + DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n")); + return; + } + + DEBUG ((DEBUG_INFO, "[TPM2PP] PPRequest=%x (PPRequestParameter=%x)\n", mPpi->Request, mPpi->RequestParameter)); + Tcg2ExecutePendingTpmRequest (PlatformAuth); +} + +/** + The handler for TPM physical presence function: + Return TPM Operation Response to OS Environment. + + @param[out] MostRecentRequest Most recent operation request. + @param[out] Response Response to the most recent operation request. + + @return Return Code for Return TPM Operation Response to OS Environment. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction ( + OUT UINT32 *MostRecentRequest, + OUT UINT32 *Response + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "[TPM2PP] ReturnOperationResponseToOsFunction\n")); + + Status = QemuTpmInitPPI (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n")); + *MostRecentRequest = 0; + *Response = 0; + return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE; + } + + *MostRecentRequest = mPpi->LastRequest; + *Response = mPpi->Response; + + return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS; +} + +/** + The handler for TPM physical presence function: + Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. + + Caution: This function may receive untrusted input. + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] RequestParameter TPM physical presence operation request parameter. + + @return Return Code for Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction ( + IN UINT32 OperationRequest, + IN UINT32 RequestParameter + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "[TPM2PP] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter)); + + Status = QemuTpmInitPPI (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n")); + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; + } + + mPpi->Request = OperationRequest; + mPpi->RequestParameter = RequestParameter; + + Flush_PPI_Cache(FALSE); //Need to flush mPpi to RAM. + + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS; +} diff --git a/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresenceLib.inf b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresenceLib.inf new file mode 100644 index 000000000000..ababaec9e01e --- /dev/null +++ b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresenceLib.inf @@ -0,0 +1,72 @@ +## @file +# Executes TPM 2.0 requests from OS or BIOS +# +# This library will check and execute TPM 2.0 request from OS or +# BIOS. The request may ask for user confirmation before +# execution. It is a clone of +# "SecurityPkg/Library/DxeTcg2PhysicalPresenceLib" with: +# +# - removed all the functions that are unreachable from +# Tcg2PhysicalPresenceLibProcessRequest() [called from platform +# BDS], or SubmitRequestToPreOSFunction() and +# ReturnOperationResponseToOsFunction() [called from Tcg2Dxe]. +# +# - replaced everything that's related to the +# TCG2_PHYSICAL_PRESENCE*_VARIABLE variables, with direct access to +# the QEMU structures. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (C) 2018, Red Hat, Inc. +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2PhysicalPresenceLibQemu + FILE_GUID = 41D3E698-9EEC-41FF-9CBB-5FE79A0CF326 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresenceLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeTcg2PhysicalPresenceLib.c + PhysicalPresenceStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DxeServicesTableLib + HiiLib + HobLib + MemoryAllocationLib + PrintLib + Tpm2CommandLib + UefiBootManagerLib + UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib + Tcg2PhysicalPresencePlatformLib + +[Protocols] + gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + ## SOMETIMES_CONSUMES ## HII + gEfiTcg2PhysicalPresenceGuid diff --git a/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.c b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.c new file mode 100644 index 000000000000..a35d73c165f6 --- /dev/null +++ b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.c @@ -0,0 +1,80 @@ +/** @file + Returns the platform specific configuration for the QEMU PPI. + + Caution: This module requires additional review when modified. + This driver will have external input - variable. + This external input must be validated carefully to avoid security issue. + +Copyright (C) 2018, Red Hat, Inc. +Copyright (c) 2018, IBM Corporation. All rights reserved.
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include + +#include + +/** + Reads QEMU PPI config from TcgPhysicalPresenceInfoHobGuid. + + @param[out] The Config structure to read to. + @param[out] The PPIinMMIO is True when the PPI is in MMIO memory space + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR Invalid HOB entry. +**/ +EFI_STATUS +TpmPPIPlatformReadConfig ( + OUT QEMU_FWCFG_TPM_CONFIG *Config, + OUT BOOLEAN *PPIinMMIO + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + TCG_PHYSICAL_PRESENCE_INFO *pPPInfo; + + // + // Find the TPM Physical Presence HOB + // + GuidHob = GetFirstGuidHob (&gEfiTcgPhysicalPresenceInfoHobGuid); + + if (GuidHob == NULL) { + return EFI_NOT_FOUND; + } + + pPPInfo = (TCG_PHYSICAL_PRESENCE_INFO *)GET_GUID_HOB_DATA (GuidHob); + + if (pPPInfo->PpiAddress == 0 || pPPInfo->PpiAddress == ~0) { + return EFI_NOT_FOUND; + } else { + Config->PpiAddress = pPPInfo->PpiAddress; + } + + if (pPPInfo->TpmVersion == UEFIPAYLOAD_TPM_VERSION_1_2) { + Config->TpmVersion = QEMU_TPM_VERSION_1_2; + } else if (pPPInfo->TpmVersion == UEFIPAYLOAD_TPM_VERSION_2) { + Config->TpmVersion = QEMU_TPM_VERSION_2; + } else { + return EFI_UNSUPPORTED; + } + + if (pPPInfo->PpiVersion == UEFIPAYLOAD_TPM_PPI_VERSION_NONE) { + Config->PpiVersion = QEMU_TPM_PPI_VERSION_NONE; + } else if (pPPInfo->PpiVersion == UEFIPAYLOAD_TPM_PPI_VERSION_1_30) { + Config->PpiVersion = QEMU_TPM_PPI_VERSION_1_30; + } else { + return EFI_UNSUPPORTED; + } + + *PPIinMMIO = FALSE; + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf new file mode 100644 index 000000000000..1201453db884 --- /dev/null +++ b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf @@ -0,0 +1,44 @@ +## @file +# Returns the platform specific configuration for the QEMU PPI. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (C) 2018, Red Hat, Inc. +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2PhysicalPresencePlatformLibUefipayload + FILE_GUID = F5967F4F-B53F-4669-91A5-A3DA0F30AF22 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresencePlatformLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[Sources] + DxeTcg2PhysicalPresencePlatformLib.c + +[LibraryClasses] + BlParseLib + HobLib + DebugLib + DxeServicesTableLib + +[Guids] + gEfiTcgPhysicalPresenceInfoHobGuid diff --git a/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/PhysicalPresenceStrings.uni b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/PhysicalPresenceStrings.uni new file mode 100644 index 000000000000..ea9ff41a1fe7 --- /dev/null +++ b/UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/PhysicalPresenceStrings.uni @@ -0,0 +1,38 @@ +/** @file + String definitions for TPM 2.0 physical presence confirm text. + +Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#langdef en-US "English" + +#string TPM_HEAD_STR #language en-US "A configuration change was requested to %s this computer's TPM (Trusted Platform Module)\n\n" + +#string TPM_ACCEPT_KEY #language en-US "Press F10 " +#string TPM_CAUTION_KEY #language en-US "Press F12 " +#string TPM_REJECT_KEY #language en-US "to %s the TPM \nPress ESC to reject this change request and continue\n" + +#string TPM_CLEAR #language en-US "clear" +#string TPM_SET_PCR_BANKS #language en-US "change the boot measurements to use PCR bank(s) of" +#string TPM_CHANGE_EPS #language en-US "clear and change identity of" + +#string TPM_NO_PPI_INFO #language en-US "to approve future Operating System requests " + +#string TPM_WARNING_CLEAR #language en-US "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted by these keys. " +#string TPM_WARNING_SET_PCR_BANKS_1 #language en-US "WARNING: Changing the PCR bank(s) of the boot measurements may prevent the Operating System from properly processing the measurements. Please check if your Operating System supports the new PCR bank(s).\n\n" +#string TPM_WARNING_SET_PCR_BANKS_2 #language en-US "WARNING: Secrets in the TPM that are bound to the boot state of your machine may become unusable.\n\n" +#string TPM_WARNING_CHANGE_EPS_1 #language en-US "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted with these keys.\n\n" +#string TPM_WARNING_CHANGE_EPS_2 #language en-US "WARNING: Changing the identity of the TPM may require additional steps to establish trust into the new identity.\n\n" + +#string TCG_STORAGE_HEAD_STR #language en-US "A configuration change was requested to %s on subsequent boots\n\n" + +#string TCG_STORAGE_ACCEPT_KEY #language en-US "Press F10 " +#string TCG_STORAGE_CAUTION_KEY #language en-US "Press F12 " +#string TCG_STORAGE_REJECT_KEY #language en-US "to %s\nPress ESC to reject this change request and continue\n" + +#string TCG_STORAGE_NO_PPI_INFO #language en-US "to approve future Operating System requests " + +#string TCG_STORAGE_ENABLE_BLOCK_SID #language en-US "issue a Block SID authentication command" +#string TCG_STORAGE_DISABLE_BLOCK_SID #language en-US "disable issuing a Block SID authentication command" diff --git a/UefiPayloadPkg/Library/TcgPhysicalPresenceLibNull/DxeTcgPhysicalPresenceLib.c b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibNull/DxeTcgPhysicalPresenceLib.c new file mode 100644 index 000000000000..edcdb9f787f7 --- /dev/null +++ b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibNull/DxeTcgPhysicalPresenceLib.c @@ -0,0 +1,19 @@ +/** @file + NULL TcgPhysicalPresenceLib library instance + + Copyright (c) 2018, Red Hat, Inc. + Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +EFI_STATUS +EFIAPI +TcgPhysicalPresenceLibProcessRequest ( + VOID + ) +{ + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/Library/TcgPhysicalPresenceLibNull/DxeTcgPhysicalPresenceLib.inf b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibNull/DxeTcgPhysicalPresenceLib.inf new file mode 100644 index 000000000000..61284acbb0df --- /dev/null +++ b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibNull/DxeTcgPhysicalPresenceLib.inf @@ -0,0 +1,29 @@ +## @file +# NULL TcgPhysicalPresenceLib library instance +# +# Under SecurityPkg, the corresponding library instance will check and +# execute TPM 1.2 request from OS or BIOS; the request may ask for user +# confirmation before execution. This Null instance implements a no-op +# Tcg2PhysicalPresenceLibProcessRequest(), without user interaction. +# +# Copyright (C) 2018, Red Hat, Inc. +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeTcgPhysicalPresenceLibNull + FILE_GUID = F5967F4F-B53F-4669-91A5-A3DA0F30AF22 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = TcgPhysicalPresenceLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +[Sources] + DxeTcgPhysicalPresenceLib.c + +[Packages] + MdePkg/MdePkg.dec + SecurityPkg/SecurityPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec diff --git a/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.c b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.c new file mode 100644 index 000000000000..182eff766aae --- /dev/null +++ b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.c @@ -0,0 +1,1710 @@ +/** @file + + Execute pending TPM requests from OS or BIOS and Lock TPM. + + It is a clone of + "SecurityPkg/Library/DxeTcgPhysicalPresenceLib" with: + + - add: access to QEMU_TPM_PPI structures + + - TBD: Code cleanup to remove + PHYSICAL_PRESENCE*_VARIABLE variables, because we are using direct access to + the QEMU structures. + + Caution: This module requires additional review when modified. + This driver will have external input - variable. + This external input must be validated carefully to avoid security issue. + + + ExecutePendingTpmRequest() will receive untrusted input and do validation. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIRM_BUFFER_SIZE 4096 + +EFI_HII_HANDLE mPpStringPackHandle; + +/* Wait 3 minutes for user input */ +#define TIMEOUT (1000 * 1000 * 60 * 3) + +STATIC volatile QEMU_TPM_PPI *mPpi; + +#define CACHELINE_SIZE 64 + +/** + Add Function to flush cached PPI data to memory + Need to Flush cache to RAM otherwise mPpi are not stored ... + + @param[in] FLUSH_ALL_CACHE Flush whole Cache. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR PPI address is invalid or Len is invalid. +**/ +EFI_STATUS +Flush_PPI_Cache12 ( + BOOLEAN FLUSH_ALL_CACHE + ) +{ + EFI_PHYSICAL_ADDRESS Ppi_address = (UINTN)mPpi; + UINTN Param_Len = (sizeof(QEMU_TPM_PPI) -1) | (CACHELINE_SIZE-1); + + if (( Ppi_address == (UINTN)NULL) || (Param_Len <=0)) return EFI_PROTOCOL_ERROR; + + DEBUG ((DEBUG_INFO, "[TPMPP] Address=%p Len=%X\n", Ppi_address, Param_Len)); + + switch (FLUSH_ALL_CACHE) + { + case 0: //Flush Only mPPI struct + for (EFI_PHYSICAL_ADDRESS Flush=Ppi_address; Flush <= Ppi_address+Param_Len; Flush+=CACHELINE_SIZE) { + AsmFlushCacheLine((char*)Flush); + //DEBUG ((DEBUG_INFO, "[TPMPP] Flush cache addr=%p\n", Flush)); + } + break; + case 1: + default: + AsmWbinvd (); //Flush All cache + //DEBUG ((DEBUG_INFO, "[TPMPP] Flush whole cache\n")); + break; + } + + return EFI_SUCCESS; +} + + +/** + Initializes QEMU PPI memory region. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR PPI address is invalid. +**/ +STATIC +EFI_STATUS +QemuTpmInitPPI12 ( + VOID + ) +{ + EFI_STATUS Status; + QEMU_FWCFG_TPM_CONFIG Config; + BOOLEAN PPIinMMIO; + EFI_PHYSICAL_ADDRESS PpiAddress64; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINTN Idx; + + if (mPpi != NULL) { + return EFI_SUCCESS; + } + + Status = TpmPPIPlatformReadConfig (&Config, &PPIinMMIO); + if (EFI_ERROR (Status)) { + return Status; + } + + mPpi = (QEMU_TPM_PPI *)(UINTN)Config.PpiAddress; + if (mPpi == NULL) { + return EFI_PROTOCOL_ERROR; + } + + DEBUG ((DEBUG_INFO, "[TPMPP] mPpi=%p version=%d\n", mPpi, Config.TpmVersion)); + + PpiAddress64 = (UINTN)mPpi; + if ((PpiAddress64 & ~(UINT64)EFI_PAGE_MASK) != + ((PpiAddress64 + sizeof *mPpi - 1) & ~(UINT64)EFI_PAGE_MASK)) + { + DEBUG ((DEBUG_ERROR, "[TPMPP] mPpi crosses a page boundary\n")); + goto InvalidPpiAddress; + } + + Status = gDS->GetMemorySpaceDescriptor (PpiAddress64, &Descriptor); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto InvalidPpiAddress; + } + + if (PPIinMMIO) { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent)) { + DEBUG ((DEBUG_ERROR, "[TPMPP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } + } else { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) { + DEBUG ((DEBUG_ERROR, "[TPMPP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } + } + + for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) { + mPpi->Func[Idx] = 0; + } + + //if (Config.TpmVersion == QEMU_TPM_VERSION_2) { + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_NO_ACTION] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_CLEAR] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_CHANGE_EPS] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID] = TPM_PPI_FLAGS; + // mPpi->Func[TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID] = TPM_PPI_FLAGS; + //} + + if (mPpi->In == 0) { + mPpi->In = 1; + mPpi->Request = TCG_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->LastRequest = TCG_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->NextStep = TCG_PHYSICAL_PRESENCE_NO_ACTION; + } + + return EFI_SUCCESS; + +InvalidPpiAddress: + mPpi = NULL; + return EFI_PROTOCOL_ERROR; +} + +/** + Check if there is a valid physical presence command request. + + This API should be invoked in BIOS boot phase to process pending request. + + Caution: This function may receive untrusted input. + + If OperationRequest < 128, then ASSERT(). + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] ManagementFlags BIOS TPM Management Flags. + @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI. + True, it indicates the command doesn't require user confirm. + False, it indicates the command need user confirm from UI. + + @retval TRUE Physical Presence operation command is valid. + @retval FALSE Physical Presence operation command is invalid. +**/ +BOOLEAN +EFIAPI +TcgPpVendorLibHasValidRequest ( + IN UINT32 OperationRequest, + IN UINT32 ManagementFlags, + OUT BOOLEAN *RequestConfirmed + ) +{ + ASSERT (OperationRequest >= TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION); + return FALSE; +} + +/** + Get string by string id from HII Interface. + + @param[in] Id String ID. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +PhysicalPresenceGetStringById ( + IN EFI_STRING_ID Id + ) +{ + return HiiGetString (mPpStringPackHandle, Id, NULL); +} + +/** + Get TPM physical presence permanent flags. + + @param[in] TcgProtocol EFI TCG Protocol instance. + @param[out] LifetimeLock physicalPresenceLifetimeLock permanent flag. + @param[out] CmdEnable physicalPresenceCMDEnable permanent flag. + + @retval EFI_SUCCESS Flags were returns successfully. + @retval other Failed to locate EFI TCG Protocol. + +**/ +EFI_STATUS +GetTpmCapability ( + IN EFI_TCG_PROTOCOL *TcgProtocol, + OUT BOOLEAN *LifetimeLock, + OUT BOOLEAN *CmdEnable + ) +{ + EFI_STATUS Status; + TPM_RQU_COMMAND_HDR *TpmRqu; + TPM_RSP_COMMAND_HDR *TpmRsp; + UINT32 *SendBufPtr; + UINT8 SendBuffer[sizeof (*TpmRqu) + sizeof (UINT32) * 3]; + TPM_PERMANENT_FLAGS *TpmPermanentFlags; + UINT8 RecvBuffer[40]; + + // + // Fill request header + // + TpmRsp = (TPM_RSP_COMMAND_HDR *)RecvBuffer; + TpmRqu = (TPM_RQU_COMMAND_HDR *)SendBuffer; + + TpmRqu->tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); + TpmRqu->paramSize = SwapBytes32 (sizeof (SendBuffer)); + TpmRqu->ordinal = SwapBytes32 (TPM_ORD_GetCapability); + + // + // Set request parameter + // + SendBufPtr = (UINT32 *)(TpmRqu + 1); + WriteUnaligned32 (SendBufPtr++, SwapBytes32 (TPM_CAP_FLAG)); + WriteUnaligned32 (SendBufPtr++, SwapBytes32 (sizeof (TPM_CAP_FLAG_PERMANENT))); + WriteUnaligned32 (SendBufPtr, SwapBytes32 (TPM_CAP_FLAG_PERMANENT)); + + Status = TcgProtocol->PassThroughToTpm ( + TcgProtocol, + sizeof (SendBuffer), + (UINT8 *)TpmRqu, + sizeof (RecvBuffer), + (UINT8 *)&RecvBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((TpmRsp->tag != SwapBytes16 (TPM_TAG_RSP_COMMAND)) || (TpmRsp->returnCode != 0)) { + return EFI_DEVICE_ERROR; + } + + TpmPermanentFlags = (TPM_PERMANENT_FLAGS *)&RecvBuffer[sizeof (TPM_RSP_COMMAND_HDR) + sizeof (UINT32)]; + + if (LifetimeLock != NULL) { + *LifetimeLock = TpmPermanentFlags->physicalPresenceLifetimeLock; + } + + if (CmdEnable != NULL) { + *CmdEnable = TpmPermanentFlags->physicalPresenceCMDEnable; + } + + return Status; +} + +/** + Issue TSC_PhysicalPresence command to TPM. + + @param[in] TcgProtocol EFI TCG Protocol instance. + @param[in] PhysicalPresence The state to set the TPM's Physical Presence flags. + + @retval EFI_SUCCESS TPM executed the command successfully. + @retval EFI_SECURITY_VIOLATION TPM returned error when executing the command. + @retval other Failed to locate EFI TCG Protocol. + +**/ +EFI_STATUS +TpmPhysicalPresence ( + IN EFI_TCG_PROTOCOL *TcgProtocol, + IN TPM_PHYSICAL_PRESENCE PhysicalPresence + ) +{ + EFI_STATUS Status; + TPM_RQU_COMMAND_HDR *TpmRqu; + TPM_PHYSICAL_PRESENCE *TpmPp; + TPM_RSP_COMMAND_HDR TpmRsp; + UINT8 Buffer[sizeof (*TpmRqu) + sizeof (*TpmPp)]; + + TpmRqu = (TPM_RQU_COMMAND_HDR *)Buffer; + TpmPp = (TPM_PHYSICAL_PRESENCE *)(TpmRqu + 1); + + TpmRqu->tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); + TpmRqu->paramSize = SwapBytes32 (sizeof (Buffer)); + TpmRqu->ordinal = SwapBytes32 (TSC_ORD_PhysicalPresence); + WriteUnaligned16 (TpmPp, (TPM_PHYSICAL_PRESENCE)SwapBytes16 (PhysicalPresence)); + + Status = TcgProtocol->PassThroughToTpm ( + TcgProtocol, + sizeof (Buffer), + (UINT8 *)TpmRqu, + sizeof (TpmRsp), + (UINT8 *)&TpmRsp + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (TpmRsp.tag != SwapBytes16 (TPM_TAG_RSP_COMMAND)) { + return EFI_DEVICE_ERROR; + } + + if (TpmRsp.returnCode != 0) { + // + // If it fails, some requirements may be needed for this command. + // + return EFI_SECURITY_VIOLATION; + } + + return Status; +} + +/** + Issue a TPM command for which no additional output data will be returned. + + @param[in] TcgProtocol EFI TCG Protocol instance. + @param[in] Ordinal TPM command code. + @param[in] AdditionalParameterSize Additional parameter size. + @param[in] AdditionalParameters Pointer to the Additional parameters. + + @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or + receiving response from TPM. + @retval Others Return code from the TPM device after command execution. + +**/ +UINT32 +TpmCommandNoReturnData ( + IN EFI_TCG_PROTOCOL *TcgProtocol, + IN TPM_COMMAND_CODE Ordinal, + IN UINTN AdditionalParameterSize, + IN VOID *AdditionalParameters + ) +{ + EFI_STATUS Status; + TPM_RQU_COMMAND_HDR *TpmRqu; + TPM_RSP_COMMAND_HDR TpmRsp; + UINT32 Size; + + TpmRqu = (TPM_RQU_COMMAND_HDR *)AllocatePool (sizeof (*TpmRqu) + AdditionalParameterSize); + if (TpmRqu == NULL) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + + TpmRqu->tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); + Size = (UINT32)(sizeof (*TpmRqu) + AdditionalParameterSize); + TpmRqu->paramSize = SwapBytes32 (Size); + TpmRqu->ordinal = SwapBytes32 (Ordinal); + CopyMem (TpmRqu + 1, AdditionalParameters, AdditionalParameterSize); + + Status = TcgProtocol->PassThroughToTpm ( + TcgProtocol, + Size, + (UINT8 *)TpmRqu, + (UINT32)sizeof (TpmRsp), + (UINT8 *)&TpmRsp + ); + FreePool (TpmRqu); + if (EFI_ERROR (Status) || (TpmRsp.tag != SwapBytes16 (TPM_TAG_RSP_COMMAND))) { + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + } + + return SwapBytes32 (TpmRsp.returnCode); +} + +/** + Execute physical presence operation requested by the OS. + + @param[in] TcgProtocol EFI TCG Protocol instance. + @param[in] CommandCode Physical presence operation value. + @param[in, out] PpiFlags The physical presence interface flags. + + @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Unknown physical presence operation. + @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or + receiving response from TPM. + @retval Others Return code from the TPM device after command execution. + +**/ +UINT32 +ExecutePhysicalPresence ( + IN EFI_TCG_PROTOCOL *TcgProtocol, + IN UINT32 CommandCode, + IN OUT EFI_PHYSICAL_PRESENCE_FLAGS *PpiFlags + ) +{ + BOOLEAN BoolVal; + UINT32 TpmResponse; + UINT32 InData[5]; + + switch (CommandCode) { + case PHYSICAL_PRESENCE_ENABLE: + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_PhysicalEnable, + 0, + NULL + ); + + case PHYSICAL_PRESENCE_DISABLE: + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_PhysicalDisable, + 0, + NULL + ); + + case PHYSICAL_PRESENCE_ACTIVATE: + BoolVal = FALSE; + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_PhysicalSetDeactivated, + sizeof (BoolVal), + &BoolVal + ); + + case PHYSICAL_PRESENCE_DEACTIVATE: + BoolVal = TRUE; + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_PhysicalSetDeactivated, + sizeof (BoolVal), + &BoolVal + ); + + case PHYSICAL_PRESENCE_CLEAR: + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_ForceClear, + 0, + NULL + ); + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE, PpiFlags); + if (TpmResponse == 0) { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ACTIVATE, PpiFlags); + } + + return TpmResponse; + + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DEACTIVATE, PpiFlags); + if (TpmResponse == 0) { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DISABLE, PpiFlags); + } + + return TpmResponse; + + case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE: + BoolVal = TRUE; + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_SetOwnerInstall, + sizeof (BoolVal), + &BoolVal + ); + + case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE: + BoolVal = FALSE; + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_SetOwnerInstall, + sizeof (BoolVal), + &BoolVal + ); + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: + // + // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE + // PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE will be executed after reboot + // + if ((PpiFlags->PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); + PpiFlags->PPFlags |= TCG_VENDOR_LIB_FLAG_RESET_TRACK; + } else { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE, PpiFlags); + PpiFlags->PPFlags &= ~TCG_VENDOR_LIB_FLAG_RESET_TRACK; + } + + return TpmResponse; + + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE, PpiFlags); + if (TpmResponse == 0) { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DEACTIVATE_DISABLE, PpiFlags); + } + + return TpmResponse; + + case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: + InData[0] = SwapBytes32 (TPM_SET_STCLEAR_DATA); // CapabilityArea + InData[1] = SwapBytes32 (sizeof (UINT32)); // SubCapSize + InData[2] = SwapBytes32 (TPM_SD_DEFERREDPHYSICALPRESENCE); // SubCap + InData[3] = SwapBytes32 (sizeof (UINT32)); // SetValueSize + InData[4] = SwapBytes32 (1); // UnownedFieldUpgrade; bit0 + return TpmCommandNoReturnData ( + TcgProtocol, + TPM_ORD_SetCapability, + sizeof (UINT32) * 5, + InData + ); + + case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH: + // + // TPM_SetOperatorAuth + // This command requires UI to prompt user for Auth data + // Here it is NOT implemented + // + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + + case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR, PpiFlags); + if (TpmResponse == 0) { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); + } + + return TpmResponse; + + case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE: + PpiFlags->PPFlags &= ~TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION; + return 0; + + case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE: + PpiFlags->PPFlags |= TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION; + return 0; + + case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE: + PpiFlags->PPFlags &= ~TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR; + return 0; + + case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE: + PpiFlags->PPFlags |= TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR; + return 0; + + case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE: + PpiFlags->PPFlags &= ~TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_MAINTENANCE; + return 0; + + case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE: + PpiFlags->PPFlags |= TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_MAINTENANCE; + return 0; + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: + // + // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_CLEAR + // PHYSICAL_PRESENCE_CLEAR will be executed after reboot. + // + if ((PpiFlags->PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); + PpiFlags->PPFlags |= TCG_VENDOR_LIB_FLAG_RESET_TRACK; + } else { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR, PpiFlags); + PpiFlags->PPFlags &= ~TCG_VENDOR_LIB_FLAG_RESET_TRACK; + } + + return TpmResponse; + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: + // + // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE + // PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE will be executed after reboot. + // + if ((PpiFlags->PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); + PpiFlags->PPFlags |= TCG_VENDOR_LIB_FLAG_RESET_TRACK; + } else { + TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE, PpiFlags); + PpiFlags->PPFlags &= ~TCG_VENDOR_LIB_FLAG_RESET_TRACK; + } + + return TpmResponse; + + default: + ; + } + + return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; +} + +/** + Read the specified key for user confirmation. + + @param[in] CautionKey If true, F12 is used as confirm key; + If false, ENTER is used as confirm key. + + @retval TRUE User confirmed the changes by input. + @retval FALSE User discarded the changes or device error. + +**/ +BOOLEAN +ReadUserKey ( + IN BOOLEAN CautionKey, + IN UINTN Timeout + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINT16 InputKey; + UINTN Delay; + + Delay = Timeout / 50; + + InputKey = 0; +do { + Status = gBS->CheckEvent (gST->ConIn->WaitForKey); + if (!EFI_ERROR (Status)) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + + if (Key.ScanCode == SCAN_ESC) { + InputKey = Key.ScanCode; + } + + if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && !CautionKey) { + InputKey = Key.UnicodeChar; + } + + if ((Key.ScanCode == SCAN_F12) && CautionKey) { + InputKey = Key.ScanCode; + } + } + gBS->Stall (50); + Delay--; + } while (InputKey == 0 && Delay > 0); + + if (Delay == 0) { + return FALSE; + } + + if (InputKey != SCAN_ESC) { + return TRUE; + } + + return FALSE; +} + +/** + The constructor function register UNI strings into imageHandle. + + It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor successfully added string package. + @retval Other value The constructor can't add string package. + +**/ +EFI_STATUS +EFIAPI +TcgPhysicalPresenceLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mPpStringPackHandle = HiiAddPackages (&gEfiPhysicalPresenceGuid, ImageHandle, DxeTcgPhysicalPresenceLibStrings, NULL); + ASSERT (mPpStringPackHandle != NULL); + + return EFI_SUCCESS; +} + +/** + Display the confirm text and get user confirmation. + + @param[in] TpmPpCommand The requested TPM physical presence command. + + @retval TRUE The user has confirmed the changes. + @retval FALSE The user doesn't confirm the changes. +**/ +BOOLEAN +UserConfirm ( + IN UINT32 TpmPpCommand + ) +{ + CHAR16 *ConfirmText; + CHAR16 *TmpStr1; + CHAR16 *TmpStr2; + UINTN BufSize; + BOOLEAN CautionKey; + UINT16 Index; + CHAR16 DstStr[81]; + + TmpStr2 = NULL; + CautionKey = FALSE; + BufSize = CONFIRM_BUFFER_SIZE; + ConfirmText = AllocateZeroPool (BufSize); + ASSERT (ConfirmText != NULL); + + switch (TpmPpCommand) { + case PHYSICAL_PRESENCE_ENABLE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_DISABLE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DISABLE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_ACTIVATE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACTIVATE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_DEACTIVATE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DEACTIVATE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_CLEAR: + CautionKey = FALSE; + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE_ACTIVATE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DEACTIVATE_DISABLE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_OFF)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ALLOW_TAKE_OWNERSHIP)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DISALLOW_TAKE_OWNERSHIP)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_TURN_ON)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_TURN_OFF)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_OFF)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: + CautionKey = FALSE; + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_UNOWNED_FIELD_UPGRADE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_UPGRADE_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_MAINTAIN)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH: + // + // TPM_SetOperatorAuth + // This command requires UI to prompt user for Auth data + // Here it is NOT implemented + // + break; + + case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: + CautionKey = FALSE; + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR_TURN_ON)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR_CONT)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE: + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_PROVISION)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE: + CautionKey = FALSE; + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE: + CautionKey = FALSE; + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_MAINTAIN)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_MAINTAIN)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: + CautionKey = FALSE; + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: + CautionKey = FALSE; + TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE)); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR)); + UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR_CONT)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY)); + StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1); + FreePool (TmpStr1); + break; + + default: + ; + } + + if (TmpStr2 == NULL) { + FreePool (ConfirmText); + return FALSE; + } + + TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY)); + BufSize -= StrSize (ConfirmText); + UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2); + + DstStr[80] = L'\0'; + for (Index = 0; Index < StrLen (ConfirmText); Index += 80) { + StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1); + Print (DstStr); + } + + FreePool (TmpStr1); + FreePool (TmpStr2); + FreePool (ConfirmText); + + if (ReadUserKey (CautionKey, TIMEOUT)) { + return TRUE; + } + + return FALSE; +} + +/** + Check if there is a valid physical presence command request. Also updates parameter value + to whether the requested physical presence command already confirmed by user + + @param[in] TcgPpData EFI TCG Physical Presence request data. + @param[in] Flags The physical presence interface flags. + @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI. + True, it indicates the command doesn't require user confirm, or already confirmed + in last boot cycle by user. + False, it indicates the command need user confirm from UI. + + @retval TRUE Physical Presence operation command is valid. + @retval FALSE Physical Presence operation command is invalid. + +**/ +BOOLEAN +HaveValidTpmRequest ( + IN EFI_PHYSICAL_PRESENCE *TcgPpData, + IN EFI_PHYSICAL_PRESENCE_FLAGS Flags, + OUT BOOLEAN *RequestConfirmed + ) +{ + BOOLEAN IsRequestValid; + + *RequestConfirmed = FALSE; + + switch (TcgPpData->PPRequest) { + case PHYSICAL_PRESENCE_NO_ACTION: + *RequestConfirmed = TRUE; + return TRUE; + case PHYSICAL_PRESENCE_ENABLE: + case PHYSICAL_PRESENCE_DISABLE: + case PHYSICAL_PRESENCE_ACTIVATE: + case PHYSICAL_PRESENCE_DEACTIVATE: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: + case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE: + case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: + case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH: + if ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION) != 0) { + *RequestConfirmed = TRUE; + } + + break; + + case PHYSICAL_PRESENCE_CLEAR: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: + if ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR) != 0) { + *RequestConfirmed = TRUE; + } + + break; + + case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: + if ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_MAINTENANCE) != 0) { + *RequestConfirmed = TRUE; + } + + break; + + case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: + if (((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR) != 0) && ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION) != 0)) { + *RequestConfirmed = TRUE; + } + + break; + + case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE: + case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE: + case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE: + *RequestConfirmed = TRUE; + break; + + case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE: + case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE: + case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE: + break; + + default: + if (TcgPpData->PPRequest >= TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { + IsRequestValid = TcgPpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed); + if (!IsRequestValid) { + return FALSE; + } else { + break; + } + } else { + // + // Wrong Physical Presence command + // + return FALSE; + } + } + + if ((Flags.PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) != 0) { + // + // It had been confirmed in last boot, it doesn't need confirm again. + // + *RequestConfirmed = TRUE; + } + + // + // Physical Presence command is correct + // + return TRUE; +} + +/** + Check and execute the requested physical presence command. + + Caution: This function may receive untrusted input. + TcgPpData variable is external input, so this function will validate + its data structure to be valid value. + + @param[in] TcgProtocol EFI TCG Protocol instance. + @param[in] TcgPpData Point to the physical presence NV variable. + @param[in] Flags The physical presence interface flags. + +**/ +VOID +ExecutePendingTpmRequest ( + IN EFI_TCG_PROTOCOL *TcgProtocol, + IN EFI_PHYSICAL_PRESENCE *TcgPpData, + IN EFI_PHYSICAL_PRESENCE_FLAGS Flags + ) +{ + EFI_STATUS Status; + UINTN DataSize; + BOOLEAN RequestConfirmed; + EFI_PHYSICAL_PRESENCE_FLAGS NewFlags; + BOOLEAN ResetRequired; + UINT32 NewPPFlags; + + if (!HaveValidTpmRequest (TcgPpData, Flags, &RequestConfirmed)) { + // + // Invalid operation request. + // + DEBUG ((DEBUG_INFO, "[TPMPP] Bad TpmRequest\n")); + mPpi->Response = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + mPpi->LastRequest = mPpi->Request; + mPpi->Request = TCG_PHYSICAL_PRESENCE_NO_ACTION; + mPpi->RequestParameter = 0; + + TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE; + TcgPpData->LastPPRequest = TcgPpData->PPRequest; + TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION; + DataSize = sizeof (EFI_PHYSICAL_PRESENCE); + Status = gRT->SetVariable ( + PHYSICAL_PRESENCE_VARIABLE, + &gEfiPhysicalPresenceGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, + TcgPpData + ); + return; + } + + ResetRequired = FALSE; + if (TcgPpData->PPRequest >= TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { + NewFlags = Flags; + NewPPFlags = NewFlags.PPFlags; +// TcgPpData->PPResponse = TcgPpVendorLibExecutePendingRequest (TcgPpData->PPRequest, &NewPPFlags, &ResetRequired); //Modif H.E To be fixed + NewFlags.PPFlags = (UINT8)NewPPFlags; + } else { + if (!RequestConfirmed) { + // Clear screen + if (gST != NULL && gST->ConOut != NULL) { + gST->ConOut->ClearScreen (gST->ConOut); + } + + // + // Print confirm text and wait for approval. + // + RequestConfirmed = UserConfirm (TcgPpData->PPRequest); + } + + // + // Execute requested physical presence command + // + TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT; + mPpi->Response = TCG_PP_OPERATION_RESPONSE_USER_ABORT; + NewFlags = Flags; + if (RequestConfirmed) { + TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &NewFlags); + mPpi->Response = TcgPpData->PPResponse; + } + } + + // + // Save the flags if it is updated. + // + if (CompareMem (&Flags, &NewFlags, sizeof (EFI_PHYSICAL_PRESENCE_FLAGS)) != 0) { + Status = gRT->SetVariable ( + PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiPhysicalPresenceGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (EFI_PHYSICAL_PRESENCE_FLAGS), + &NewFlags + ); + if (EFI_ERROR (Status)) { + return; + } + } + + // + // Clear request + // + if ((NewFlags.PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) { + TcgPpData->LastPPRequest = TcgPpData->PPRequest; + TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION; + + mPpi->LastRequest = mPpi->Request; + mPpi->Request = PHYSICAL_PRESENCE_NO_ACTION; + mPpi->RequestParameter = 0; + } + + // + // Save changes + // + DataSize = sizeof (EFI_PHYSICAL_PRESENCE); + Status = gRT->SetVariable ( + PHYSICAL_PRESENCE_VARIABLE, + &gEfiPhysicalPresenceGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, + TcgPpData + ); + if (EFI_ERROR (Status)) { + return; + } + + if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) { + return; + } + + // + // Reset system to make new TPM settings in effect + // + switch (TcgPpData->LastPPRequest) { + case PHYSICAL_PRESENCE_ACTIVATE: + case PHYSICAL_PRESENCE_DEACTIVATE: + case PHYSICAL_PRESENCE_CLEAR: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: + case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: + case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: + case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: + case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: + break; + default: + if (TcgPpData->LastPPRequest >= TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) { + if (ResetRequired) { + break; + } else { + return; + } + } + + if (TcgPpData->PPRequest != PHYSICAL_PRESENCE_NO_ACTION) { + break; + } + + return; + } + + Flush_PPI_Cache12(TRUE); //Need to Flush cache to RAM otherwise mPpi are not stored in RAM. + + if (RequestConfirmed) { + Print (L"\n\nRebooting system to apply changes to TPM settings\n"); + // Pause so user see that is the system is about to reboot + MicroSecondDelay(3000*1000); + } + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + ASSERT (FALSE); +} + +/** + Check and execute the pending TPM request and Lock TPM. + + The TPM request may come from OS or BIOS. This API will display request information and wait + for user confirmation if TPM request exists. The TPM request will be sent to TPM device after + the TPM request is confirmed, and one or more reset may be required to make TPM request to + take effect. At last, it will lock TPM to prevent TPM state change by malware. + + This API should be invoked after console in and console out are all ready as they are required + to display request information and get user input to confirm the request. This API should also + be invoked as early as possible as TPM is locked in this function. + + @retval EFI_SUCCESS Flags were returns successfully. + @retval other Failed to process. + +**/ +EFI_STATUS +EFIAPI +TcgPhysicalPresenceLibProcessRequest ( + VOID + ) +{ + EFI_STATUS Status; + BOOLEAN LifetimeLock; + BOOLEAN CmdEnable; + UINTN DataSize; + EFI_PHYSICAL_PRESENCE TcgPpData; + EFI_TCG_PROTOCOL *TcgProtocol; +// EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol; + EFI_PHYSICAL_PRESENCE_FLAGS PpiFlags; + + Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = QemuTpmInitPPI12 (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPMPP] no PPI\n")); + return Status; + } + + // + // Check S4 resume + // + if (GetBootModeHob () == BOOT_ON_S4_RESUME) { + DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n")); + return EFI_SUCCESS; + } + + // + // Initialize physical presence flags. + // + DataSize = sizeof (EFI_PHYSICAL_PRESENCE_FLAGS); + Status = gRT->GetVariable ( + PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiPhysicalPresenceGuid, + NULL, + &DataSize, + &PpiFlags + ); + if (EFI_ERROR (Status)) { + PpiFlags.PPFlags = TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION; + Status = gRT->SetVariable ( + PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiPhysicalPresenceGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (EFI_PHYSICAL_PRESENCE_FLAGS), + &PpiFlags + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[TPM] Set physical presence flag failed, Status = %r\n", Status)); + return Status; + } + } + + DEBUG ((DEBUG_INFO, "[TPM] PpiFlags = %x\n", PpiFlags.PPFlags)); + + // + // This flags variable controls whether physical presence is required for TPM command. + // It should be protected from malicious software. We set it as read-only variable here. + // + //Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol); + //if (!EFI_ERROR (Status)) { + //Status = VariableLockProtocol->RequestToLock ( + // VariableLockProtocol, + // PHYSICAL_PRESENCE_FLAGS_VARIABLE, + // &gEfiPhysicalPresenceGuid + // ); + // if (EFI_ERROR (Status)) { + // DEBUG ((DEBUG_ERROR, "[TPM] Error when lock variable %s, Status = %r\n", PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); + // ASSERT_EFI_ERROR (Status); + // } + //} + + // + // Initialize physical presence variable. + // + DataSize = sizeof (EFI_PHYSICAL_PRESENCE); + Status = gRT->GetVariable ( + PHYSICAL_PRESENCE_VARIABLE, + &gEfiPhysicalPresenceGuid, + NULL, + &DataSize, + &TcgPpData + ); + if (EFI_ERROR (Status)) { + ZeroMem ((VOID *)&TcgPpData, sizeof (TcgPpData)); + DataSize = sizeof (EFI_PHYSICAL_PRESENCE); + Status = gRT->SetVariable ( + PHYSICAL_PRESENCE_VARIABLE, + &gEfiPhysicalPresenceGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, + &TcgPpData + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[TPM] Set physical presence variable failed, Status = %r\n", Status)); + return Status; + } + } + + //Align Variable with mPpi + if ((mPpi->Request != TcgPpData.PPRequest) || ( mPpi->LastRequest != TcgPpData.LastPPRequest) || ( mPpi->Response != TcgPpData.PPResponse)) { + DEBUG ((DEBUG_INFO, "[TPM] Align variable to mPpi\n")); + TcgPpData.PPRequest = mPpi->Request; + TcgPpData.LastPPRequest = mPpi->LastRequest; + TcgPpData.PPResponse = mPpi->Response; + + DataSize = sizeof (EFI_PHYSICAL_PRESENCE); + Status = gRT->SetVariable ( + PHYSICAL_PRESENCE_VARIABLE, + &gEfiPhysicalPresenceGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, + &TcgPpData + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[TPM] Set physical presence variable failed, Status = %r\n", Status)); + return Status; + } + } + DEBUG ((DEBUG_INFO, "[TPM] Flags=%x, PPRequest=%x\n", PpiFlags.PPFlags, TcgPpData.PPRequest)); + + if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) { + // + // No operation request + // + return EFI_SUCCESS; + } + + Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable); + if (EFI_ERROR (Status)) { + return Status; + } + + if (!CmdEnable) { + if (LifetimeLock) { + // + // physicalPresenceCMDEnable is locked, can't execute physical presence command. + // + return EFI_DEVICE_ERROR; + } + + Status = TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_CMD_ENABLE); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Set operator physical presence flags + // + Status = TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_PRESENT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Execute pending TPM request. + // + ExecutePendingTpmRequest (TcgProtocol, &TcgPpData, PpiFlags); + DEBUG ((DEBUG_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse)); + + // + // Lock physical presence. + // + TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK); + + return EFI_SUCCESS; +} + +/** + Check if the pending TPM request needs user input to confirm. + + The TPM request may come from OS. This API will check if TPM request exists and need user + input to confirmation. + + @retval TRUE TPM needs input to confirm user physical presence. + @retval FALSE TPM doesn't need input to confirm user physical presence. + +**/ +BOOLEAN +EFIAPI +TcgPhysicalPresenceLibNeedUserConfirm ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_PRESENCE TcgPpData; + UINTN DataSize; + BOOLEAN RequestConfirmed; + BOOLEAN LifetimeLock; + BOOLEAN CmdEnable; + EFI_TCG_PROTOCOL *TcgProtocol; + EFI_PHYSICAL_PRESENCE_FLAGS PpiFlags; + + Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Check Tpm requests + // + DataSize = sizeof (EFI_PHYSICAL_PRESENCE); + Status = gRT->GetVariable ( + PHYSICAL_PRESENCE_VARIABLE, + &gEfiPhysicalPresenceGuid, + NULL, + &DataSize, + &TcgPpData + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + DataSize = sizeof (EFI_PHYSICAL_PRESENCE_FLAGS); + Status = gRT->GetVariable ( + PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiPhysicalPresenceGuid, + NULL, + &DataSize, + &PpiFlags + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) { + // + // No operation request + // + return FALSE; + } + + if (!HaveValidTpmRequest (&TcgPpData, PpiFlags, &RequestConfirmed)) { + // + // Invalid operation request. + // + return FALSE; + } + + // + // Check Tpm Capability + // + Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (!CmdEnable) { + if (LifetimeLock) { + // + // physicalPresenceCMDEnable is locked, can't execute physical presence command. + // + return FALSE; + } + } + + if (!RequestConfirmed) { + // + // Need UI to confirm + // + return TRUE; + } + + return FALSE; +} + +/** + The handler for TPM physical presence function: + Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. + + Caution: This function may receive untrusted input. + + @param[in] OperationRequest TPM physical presence operation request. + @param[in] RequestParameter TPM physical presence operation request parameter. + + @return Return Code for Submit TPM Operation Request to Pre-OS Environment and + Submit TPM Operation Request to Pre-OS Environment 2. +**/ +UINT32 +EFIAPI +TcgPhysicalPresenceLibSubmitRequestToPreOSFunction ( + IN UINT32 OperationRequest, + IN UINT32 RequestParameter + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "[TPMPP] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter)); + + Status = QemuTpmInitPPI12 (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[TPMPP] no PPI\n")); + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; + } + + mPpi->Request = OperationRequest; + mPpi->RequestParameter = RequestParameter; + + Flush_PPI_Cache12(FALSE); //Need to flush mPpi to RAM. + + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS; +} diff --git a/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.inf b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.inf new file mode 100644 index 000000000000..af4f12ed3579 --- /dev/null +++ b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.inf @@ -0,0 +1,74 @@ +## @file +# Executes pending TPM 1.2 requests from OS or BIOS and Locks TPM +# +# This library will check and execute TPM 1.2 request from OS or BIOS. The request may +# ask for user confirmation before execution. This Library will also lock TPM physical +# presence at last. +# +# It is a clone of +# "SecurityPkg/Library/DxeTcgPhysicalPresenceLib" with: +# +# - add: access to QEMU_TPM_PPI structures +# +# - TBD: Code cleanup to remove +# PHYSICAL_PRESENCE*_VARIABLE variables, because we are using direct access to +# the QEMU structures. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeTcgPhysicalPresenceLib + MODULE_UNI_FILE = DxeTcgPhysicalPresenceLib.uni + FILE_GUID = EBC43A46-34AC-4F07-A7F5-A5394619361C + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = TcgPhysicalPresenceLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = TcgPhysicalPresenceLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeTcgPhysicalPresenceLib.c + PhysicalPresenceStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + PrintLib + HiiLib + TimerLib + Tcg2PhysicalPresencePlatformLib + +[Protocols] + gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES + gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + ## SOMETIMES_CONSUMES ## HII + ## SOMETIMES_PRODUCES ## Variable:L"PhysicalPresence" + ## SOMETIMES_CONSUMES ## Variable:L"PhysicalPresence" + ## SOMETIMES_PRODUCES ## Variable:L"PhysicalPresenceFlags" + ## SOMETIMES_CONSUMES ## Variable:L"PhysicalPresenceFlags" + gEfiPhysicalPresenceGuid diff --git a/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.uni b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.uni new file mode 100644 index 000000000000..c7fcca5c65d9 --- /dev/null +++ b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.uni @@ -0,0 +1,22 @@ +// /** @file +// Executes pending TPM 1.2 requests from OS or BIOS and Locks TPM +// +// This library will check and execute TPM 1.2 request from OS or BIOS. The request may +// ask for user confirmation before execution. This Library will also lock TPM physical +// presence at last. +// +// Caution: This module requires additional review when modified. +// This driver will have external input - variable. +// This external input must be validated carefully to avoid security issue. +// +// Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Executes pending TPM 1.2 requests from OS or BIOS and Locks TPM" + +#string STR_MODULE_DESCRIPTION #language en-US "This library will ask for user confirmation for the pending TPM physical present requests. Once confirmed, it will execute the request, and locks TPM physical presence at last. Caution: This module requires additional review when modified. This driver will have external input - variable. This external input must be validated carefully to avoid security issue." + diff --git a/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/PhysicalPresenceStrings.uni b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/PhysicalPresenceStrings.uni new file mode 100644 index 000000000000..b6ae881e3a59 --- /dev/null +++ b/UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/PhysicalPresenceStrings.uni @@ -0,0 +1,46 @@ +/** @file + String definitions for TPM 1.2 physical presence confirm text. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#langdef en-US "English" + +#string TPM_HEAD_STR #language en-US "A configuration change was requested to %s this computer's TPM (Trusted Platform Module)\n\n" +#string TPM_PPI_HEAD_STR #language en-US "A configuration change was requested to allow the Operating System to %s the computer's TPM (Trusted Platform Module) without asking for user confirmation in the future.\n\n" +#string TPM_UPGRADE_HEAD_STR #language en-US "A configuration change was requested to %s to the TPM's (Trusted Platform Module) firmware.\n\n" + +#string TPM_ACCEPT_KEY #language en-US "Press ENTER " +#string TPM_CAUTION_KEY #language en-US "Press F12 " +#string TPM_REJECT_KEY #language en-US "to %s the TPM \nPress ESC to reject this change request and continue\n" + +#string TPM_ENABLE #language en-US "enable" +#string TPM_DISABLE #language en-US "disable" +#string TPM_ACTIVATE #language en-US "activate" +#string TPM_DEACTIVATE #language en-US "deactivate" +#string TPM_CLEAR #language en-US "clear" +#string TPM_ENABLE_ACTIVATE #language en-US "enable and activate" +#string TPM_DEACTIVATE_DISABLE #language en-US "deactivate and disable" +#string TPM_ALLOW_TAKE_OWNERSHIP #language en-US "allow a user to take ownership of" +#string TPM_DISALLOW_TAKE_OWNERSHIP #language en-US "disallow a user to take ownership of" +#string TPM_TURN_ON #language en-US "enable, activate, and allow a user to take ownership of" +#string TPM_TURN_OFF #language en-US "deactivate, disable, and disallow a user to take ownership of" +#string TPM_CLEAR_TURN_ON #language en-US "clear, enable, and activate" +#string TPM_ENABLE_ACTIVATE_CLEAR #language en-US "enable, activate and clear" +#string TPM_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE #language en-US "enable, activate, clear, enable, and activate" +#string TPM_UNOWNED_FIELD_UPGRADE #language en-US "allow field upgrade" + +#string TPM_NO_PPI_PROVISION #language en-US "provision" +#string TPM_NO_PPI_MAINTAIN #language en-US "maintain" +#string TPM_NO_PPI_INFO #language en-US "to approve future Operating System requests " + +#string TPM_WARNING_MAINTAIN #language en-US "WARNING: Allowing changes to the TPM's firmware may affect the operation of the TPM and may erase information stored on the TPM.\nYou may lose all created keys and access to data encrypted by these keys.\n\n" +#string TPM_WARNING #language en-US "WARNING: Doing so might prevent security applications that rely on the TPM from functioning as expected\n\n" +#string TPM_WARNING_CLEAR #language en-US "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted by these keys. " +#string TPM_WARNING_CLEAR_CONT #language en-US "Take ownership as soon as possible after this step.\n\n" +#string TPM_NOTE_OFF #language en-US "NOTE: This action will turn off the TPM\n\n" +#string TPM_NOTE_ON #language en-US "NOTE: This action will turn on the TPM\n\n" +#string TPM_NOTE_CLEAR #language en-US "NOTE: This action does not clear the TPM, but by approving this configuration change, future actions to clear the TPM will not require user confirmation.\n\n" diff --git a/UefiPayloadPkg/NetworkDrivers/AX88179X_178A_772D_UEFI_v3.2.0_X64_signed.efi b/UefiPayloadPkg/NetworkDrivers/AX88179X_178A_772D_UEFI_v3.2.0_X64_signed.efi new file mode 100644 index 000000000000..3165cd1eca6b Binary files /dev/null and b/UefiPayloadPkg/NetworkDrivers/AX88179X_178A_772D_UEFI_v3.2.0_X64_signed.efi differ diff --git a/UefiPayloadPkg/NetworkDrivers/AX88772C_772B_772A_UEFI_V2.8.0_X64.efi b/UefiPayloadPkg/NetworkDrivers/AX88772C_772B_772A_UEFI_V2.8.0_X64.efi new file mode 100644 index 000000000000..04553deece9d Binary files /dev/null and b/UefiPayloadPkg/NetworkDrivers/AX88772C_772B_772A_UEFI_V2.8.0_X64.efi differ diff --git a/UefiPayloadPkg/NetworkDrivers/RtkUndiDxe.efi b/UefiPayloadPkg/NetworkDrivers/RtkUndiDxe.efi new file mode 100644 index 000000000000..1f839c0a4a0d Binary files /dev/null and b/UefiPayloadPkg/NetworkDrivers/RtkUndiDxe.efi differ diff --git a/UefiPayloadPkg/NetworkDrivers/RtkUsbUndiDxe.efi b/UefiPayloadPkg/NetworkDrivers/RtkUsbUndiDxe.efi new file mode 100644 index 000000000000..d206586eefbc Binary files /dev/null and b/UefiPayloadPkg/NetworkDrivers/RtkUsbUndiDxe.efi differ diff --git a/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.c b/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.c new file mode 100644 index 000000000000..f3e9785c70c4 --- /dev/null +++ b/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.c @@ -0,0 +1,174 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + + SPDX-License-Identifier: BSD-2-Clause-Patent + + + + +--*/ + +/** @file +**/ + +#include +#include +#include +#include "PlatformGopPolicy.h" + +#include +#include + +PLATFORM_GOP_POLICY_PROTOCOL mPlatformGOPPolicy; + +// +// Function implementations +// + +/** + The function will execute with as the platform policy, and gives + the Platform Lid Status. IBV/OEM can customize this code for their specific + policy action. + + @param CurrentLidStatus Gives the current LID Status + + @retval EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +GetPlatformLidStatus ( + OUT LID_STATUS *CurrentLidStatus +) +{ + *CurrentLidStatus = LidOpen; + + return EFI_SUCCESS; +} + +/** + The function will execute and gives the Video Bios Table Size and Address. + + @param VbtAddress Gives the Physical Address of Video BIOS Table + + @param VbtSize Gives the Size of Video BIOS Table + + @retval EFI_STATUS. + +**/ + +EFI_STATUS +EFIAPI +GetVbtData ( + OUT EFI_PHYSICAL_ADDRESS *VbtAddress, + OUT UINT32 *VbtSize +) +{ + EFI_STATUS Status; + UINTN FvProtocolCount; + EFI_HANDLE *FvHandles; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Index; + UINT32 AuthenticationStatus; + + UINT8 *Buffer; + UINTN VbtBufferSize; + + Buffer = 0; + FvHandles = NULL; + + if (VbtAddress == NULL || VbtSize == NULL){ + return EFI_INVALID_PARAMETER; + } + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvProtocolCount, + &FvHandles + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < FvProtocolCount; Index++) { + Status = gBS->HandleProtocol ( + FvHandles[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + VbtBufferSize = 0; + Status = Fv->ReadSection ( + Fv, + &gBmpImageGuid, + EFI_SECTION_RAW, + 0, + (void **)&Buffer, + &VbtBufferSize, + &AuthenticationStatus + ); + + if (!EFI_ERROR (Status)) { + *VbtAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + *VbtSize = (UINT32)VbtBufferSize; + Status = EFI_SUCCESS; + break; + } + } + } else { + Status = EFI_NOT_FOUND; + } + + if (FvHandles != NULL) { + gBS->FreePool (FvHandles); + FvHandles = NULL; + } + + return Status; +} + +/** + Entry point for the Platform GOP Policy Driver. + + @param ImageHandle Image handle of this driver. + @param SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. + +**/ + +EFI_STATUS +EFIAPI +PlatformGOPPolicyEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status = EFI_SUCCESS; + + gBS = SystemTable->BootServices; + + gBS->SetMem ( + &mPlatformGOPPolicy, + sizeof (PLATFORM_GOP_POLICY_PROTOCOL), + 0 + ); + + mPlatformGOPPolicy.Revision = PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01; + mPlatformGOPPolicy.GetPlatformLidStatus = GetPlatformLidStatus; + mPlatformGOPPolicy.GetVbtData = GetVbtData; + + // + // Install protocol to allow access to this Policy. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gPlatformGOPPolicyGuid, + &mPlatformGOPPolicy, + NULL + ); + + return Status; +} diff --git a/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.h b/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.h new file mode 100644 index 000000000000..9205afbd8f64 --- /dev/null +++ b/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.h @@ -0,0 +1,70 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + + SPDX-License-Identifier: BSD-2-Clause-Patent + + + + +--*/ + +/** @file +**/ + +#ifndef _PLATFORM_GOP_POLICY_PROTOCOL_H_ +#define _PLATFORM_GOP_POLICY_PROTOCOL_H_ + +#define EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID \ + { 0xec2e931b, 0x3281, 0x48a5, 0x81, 0x7, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } + +#define EFI_BMP_IMAGE_GUID \ + { 0x878AC2CC, 0x5343, 0x46F2, 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } + +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01 0x01 +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_02 x0222 + +#pragma pack(1) + +typedef enum { + LidClosed, + LidOpen, + LidStatusMax +} LID_STATUS; + +typedef enum { + Docked, + UnDocked, + DockStatusMax +} DOCK_STATUS; + +typedef +EFI_STATUS +(EFIAPI *GET_PLATFORM_LID_STATUS) ( + OUT LID_STATUS *CurrentLidStatus +); + +typedef +EFI_STATUS +(EFIAPI *GET_VBT_DATA) ( + OUT EFI_PHYSICAL_ADDRESS *VbtAddress, + OUT UINT32 *VbtSize +); + +#pragma pack() + +typedef struct _PLATFORM_GOP_POLICY_PROTOCOL { + UINT32 Revision; + GET_PLATFORM_LID_STATUS GetPlatformLidStatus; + GET_VBT_DATA GetVbtData; +} PLATFORM_GOP_POLICY_PROTOCOL; + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gPlatformGOPPolicyGuid; + +extern EFI_GUID gBmpImageGuid; + +#endif diff --git a/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf b/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf new file mode 100644 index 000000000000..a8c1d32ca811 --- /dev/null +++ b/UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf @@ -0,0 +1,44 @@ +# +# +# Copyright (c) 1999 - 2019, Intel Corporation. All rights reserved +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformGOPPolicy + FILE_GUID = 9737D7CA-D869-45e5-A5EF-75D9438688DE + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PlatformGOPPolicyEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources.common] + PlatformGopPolicy.c + +[Packages] + MdePkg/MdePkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Guids] + gBmpImageGuid + +[Protocols] + gEfiFirmwareVolume2ProtocolGuid + gPlatformGOPPolicyGuid + +[Depex] + gEfiVariableArchProtocolGuid diff --git a/UefiPayloadPkg/SdMmcMmioDxe/README.md b/UefiPayloadPkg/SdMmcMmioDxe/README.md new file mode 100644 index 000000000000..52b281841faf --- /dev/null +++ b/UefiPayloadPkg/SdMmcMmioDxe/README.md @@ -0,0 +1,213 @@ +# SdMmcMmioDxe - Universal MMIO SDHCI Driver + +## Overview + +`SdMmcMmioDxe` is a universal UEFI driver that provides support for any MMIO-mapped SDHCI controller (eMMC or SD card). Originally designed for AMD Picasso platforms, it has been extended to support any platform with MMIO-accessible SDHCI controllers through configurable Platform Configuration Database (PCD) values. + +## Key Features + +- ✅ **Universal MMIO Support**: Works with any SDHCI-compatible controller +- ✅ **Dual Controller Support**: Separate eMMC and SD controller registration +- ✅ **Configurable via PCDs**: MMIO base addresses set through build-time configuration +- ✅ **Independent Enable/Disable**: Each controller can be enabled/disabled separately +- ✅ **Backward Compatible**: Default values maintain AMD Picasso support +- ✅ **Non-Discoverable Device Framework**: Integrates with EDK2's standard infrastructure + +## Architecture + +### Components + +``` +SdMmcMmioDxe/ +├── SdMmcMmioDxe.dec # PCD definitions and package declaration +├── SdMmcMmioDxe.h # Header with type definitions +├── SdMmcMmioDxe.c # Main driver implementation +└── SdMmcMmioDxe.inf # Build configuration +``` + +### Design + +The driver registers SDHCI controllers as non-discoverable MMIO devices, allowing standard EDK2 SDHCI drivers (`SdDxe.inf` / `EmmcDxe.inf`) to manage them. It provides an override protocol to customize controller capabilities (e.g., slot type). + +## Configuration + +### PCD Definitions + +| PCD Name | Type | Default | Description | +|----------|------|---------|-------------| +| `PcdEmmcMmioBaseAddress` | UINT64 | 0xFEDD5000 | eMMC controller MMIO base address | +| `PcdSdMmioBaseAddress` | UINT64 | 0x0 | SD controller MMIO base address | + +**Token Space GUID**: `gSdMmcMmioDxeTokenSpaceGuid` + +### Setting PCDs + +#### Method 1: DSC File (Recommended) +Edit `UefiPayloadPkg.dsc`: + +```dsc +[PcdsFixedAtBuild] + # Universal MMIO SDHCI Driver PCDs + gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0xFEDD5000 + gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress|0x0 +``` + +#### Method 2: Build Command Line +```bash +build -p UefiPayloadPkg/UefiPayloadPkg.dsc -t GCC -a X64 \ + --pcd gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress=0xFEDD5000 \ + --pcd gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress=0xFEDD6000 +``` + +#### Method 3: Coreboot Integration +In `payloads/external/edk2/Makefile`: + +```makefile +ifeq ($(CONFIG_EDK2_PCO_MMIO_EMMC),y) +BUILD_STR += -D USE_PCO_MMIO_EMMC=TRUE +BUILD_STR += --pcd gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress=0xFEDD5000 +BUILD_STR += --pcd gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress=0x0 +endif +``` + +## Usage Examples + +### Example 1: AMD Picasso (Default) +```dsc +gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0xFEDD5000 +gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress|0x0 +``` +**Result**: eMMC enabled at 0xFEDD5000, SD disabled + +### Example 2: Both Controllers +```dsc +gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0xFEDD5000 +gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress|0xFEDD6000 +``` +**Result**: Both controllers enabled + +### Example 3: SD Only +```dsc +gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0x0 +gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress|0xFEDD6000 +``` +**Result**: eMMC disabled, SD enabled + +### Example 4: Custom Platform +```dsc +gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0xFE000000 +gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress|0xFE001000 +``` +**Result**: Both controllers at custom addresses + +## Driver Behavior + +### Initialization Sequence + +1. Read PCD values for eMMC and SD MMIO base addresses +2. If eMMC PCD ≠ 0: Register eMMC controller as non-discoverable device +3. If SD PCD ≠ 0: Register SD controller as non-discoverable device +4. If at least one controller registered: Install SD/MMC override protocol +5. Return success + +### Controller Registration + +Each controller is registered with: +- **Device Type**: `NonDiscoverableDeviceTypeSdhci` +- **DMA Type**: `NonDiscoverableDeviceDmaTypeCoherent` +- **MMIO Size**: 4KB (0x1000 bytes) + +### Debug Output + +Enable debug output with `-D BUILD_TARGETS=DEBUG` or `CONFIG_EDK2_DEBUG=y`: + +``` +SdMmcMmioDxe: eMMC MMIO base = 0xfedd5000 +SdMmcMmioDxe: SD MMIO base = 0x0 +SdMmcMmioDxe: eMMC controller registered at 0xfedd5000 +SdMmcMmioDxe: Registered 1 controller(s) +``` + +## Integration with Coreboot + +### Kconfig Option +```kconfig +config EDK2_PCO_MMIO_EMMC + bool "Enable MMIO eMMC driver for AMD Picasso boards in edk2" + depends on EDK2_REPO_MRCHROMEBOX + default n +``` + +### Build System +The driver is included when `USE_PCO_MMIO_EMMC=TRUE` is set in the EDK2 build. + +## Platform Support + +### Tested Platforms +- ✅ AMD Picasso (eMMC @ 0xFEDD5000) + +### Potential Platforms +- AMD Stoney Ridge +- Any platform with MMIO-accessible SDHCI controllers + +## Technical Details + +### Memory Layout +- Each controller requires 4KB of MMIO address space +- Controllers must be aligned to 4KB boundaries +- No overlap between eMMC and SD MMIO regions + +### Slot Type +By default, all controllers are registered as `EmbeddedSlot`. This can be customized via the override protocol. + +### DMA Coherency +The driver assumes DMA-coherent memory (`NonDiscoverableDeviceDmaTypeCoherent`), suitable for most x86 platforms. + +## Troubleshooting + +### Controller Not Detected +1. Verify PCD value is non-zero and correct for your platform +2. Check MMIO base address is valid (not reserved by other devices) +3. Ensure `USE_PCO_MMIO_EMMC=TRUE` is set in build +4. Review debug output for registration failures + +### Build Errors +1. Ensure all file references updated (DSC, FDF, INF) +2. Verify PCD token space GUID matches across DEC and DSC +3. Check PcdLib is included in LibraryClasses + +### Runtime Errors +1. Verify MMIO addresses don't conflict with other devices +2. Check platform firmware initializes SDHCI controller before UEFI +3. Ensure controller is not disabled in platform configuration + +## Differences from PCI-based Driver + +| Aspect | SdMmcMmioDxe (MMIO) | SdMmcPciCbDxe (PCI) | +|--------|---------------------|---------------------| +| **Discovery** | Static (PCD-based) | Dynamic (PCI enumeration) | +| **Configuration** | Build-time PCDs | Runtime PCI detection | +| **Use Case** | Fixed MMIO controllers | PCI/PCIe SDHCI devices | +| **Flexibility** | Per-platform build | Universal binary | + +## Migration from AmdPcoSdhciDxe + +The driver was renamed from `AmdPcoSdhciDxe` to `SdMmcMmioDxe` to reflect its universal nature: + +| Old | New | +|-----|-----| +| `AmdPcoSdhciDxe` | `SdMmcMmioDxe` | +| `gAmdPcoSdhciDxeTokenSpaceGuid` | `gSdMmcMmioDxeTokenSpaceGuid` | +| `AmdPcoSdhciDxeInitialize` | `SdMmcMmioDxeInitialize` | + +All functionality remains identical. + +## License + +SPDX-License-Identifier: BSD-2-Clause-Patent + +## Credits + +- Patrick Wildt +- Mario Bălănică +- CoolStar diff --git a/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.c b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.c new file mode 100644 index 000000000000..204354a7727c --- /dev/null +++ b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.c @@ -0,0 +1,184 @@ +/** @file + * + * Universal MMIO SDHCI eMMC/SD driver + * + * Copyright (c) 2017, Linaro, Ltd. All rights reserved.
+ * Copyright (c) 2022, Patrick Wildt + * Copyright (c) 2023, Mario Bălănică + * Copyright (c) 2024, CoolStar + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#include +#include +#include +#include + +#include +#include + +#include "SdMmcMmioDxe.h" + + +STATIC EFI_HANDLE mEmmcControllerHandle; +STATIC EFI_HANDLE mSdControllerHandle; + +/** + Override function for SDHCI capability bits + + @param[in] ControllerHandle The EFI_HANDLE of the controller. + @param[in] Slot The 0 based slot index. + @param[in,out] SdMmcHcSlotCapability The SDHCI capability structure. + @param[in,out] BaseClkFreq The base clock frequency value that + optionally can be updated. + + @retval EFI_SUCCESS The override function completed successfully. + @retval EFI_NOT_FOUND The specified controller or slot does not exist. + @retval EFI_INVALID_PARAMETER SdMmcHcSlotCapability is NULL + +**/ +STATIC +EFI_STATUS +EFIAPI +EmmcSdMmcCapability ( + IN EFI_HANDLE ControllerHandle, + IN UINT8 Slot, + IN OUT VOID *SdMmcHcSlotCapability, + IN OUT UINT32 *BaseClkFreq + ) +{ + SD_MMC_HC_SLOT_CAP *Capability = SdMmcHcSlotCapability; + + DEBUG ((DEBUG_BLKIO, "%a\n", __FUNCTION__)); + + if (SdMmcHcSlotCapability == NULL) { + return EFI_INVALID_PARAMETER; + } + if (ControllerHandle != mEmmcControllerHandle && ControllerHandle != mSdControllerHandle) { + return EFI_NOT_FOUND; + } + + Capability->SlotType = EmbeddedSlot; + + return EFI_SUCCESS; +} + +/** + + Override function for SDHCI controller operations + + @param[in] ControllerHandle The EFI_HANDLE of the controller. + @param[in] Slot The 0 based slot index. + @param[in] PhaseType The type of operation and whether the + hook is invoked right before (pre) or + right after (post) + @param[in,out] PhaseData The pointer to a phase-specific data. + + @retval EFI_SUCCESS The override function completed successfully. + @retval EFI_NOT_FOUND The specified controller or slot does not exist. + @retval EFI_INVALID_PARAMETER PhaseType is invalid + +**/ +STATIC +EFI_STATUS +EFIAPI +EmmcSdMmcNotifyPhase ( + IN EFI_HANDLE ControllerHandle, + IN UINT8 Slot, + IN EDKII_SD_MMC_PHASE_TYPE PhaseType, + IN OUT VOID *PhaseData + ) +{ + DEBUG ((DEBUG_INFO, "%a\n", __FUNCTION__)); + + if (ControllerHandle != mEmmcControllerHandle && ControllerHandle != mSdControllerHandle) { + return EFI_SUCCESS; + } + + ASSERT (Slot == 0); + + + return EFI_SUCCESS; +} + +STATIC EDKII_SD_MMC_OVERRIDE mSdMmcOverride = { + EDKII_SD_MMC_OVERRIDE_PROTOCOL_VERSION, + EmmcSdMmcCapability, + EmmcSdMmcNotifyPhase, +}; + +EFI_STATUS +EFIAPI +SdMmcMmioDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + UINT64 EmmcMmioBase; + UINT64 SdMmioBase; + UINTN ControllerCount = 0; + + DEBUG ((DEBUG_BLKIO, "%a\n", __FUNCTION__)); + + // Get MMIO base addresses from PCDs + EmmcMmioBase = PCD_EMMC_MMIO_BASE_ADDRESS; + SdMmioBase = PCD_SD_MMIO_BASE_ADDRESS; + + DEBUG ((DEBUG_BLKIO, "SdMmcMmioDxe: eMMC MMIO base = 0x%llx\n", EmmcMmioBase)); + DEBUG ((DEBUG_BLKIO, "SdMmcMmioDxe: SD MMIO base = 0x%llx\n", SdMmioBase)); + + // Register eMMC controller if MMIO base is non-zero + if (EmmcMmioBase != 0) { + Status = RegisterNonDiscoverableMmioDevice ( + NonDiscoverableDeviceTypeSdhci, + NonDiscoverableDeviceDmaTypeCoherent, + NULL, + &mEmmcControllerHandle, + 1, + (UINTN)EmmcMmioBase, (UINTN)0x1000); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcMmioDxe: Failed to register eMMC controller: %r\n", Status)); + } else { + DEBUG ((DEBUG_INFO, "SdMmcMmioDxe: eMMC controller registered at 0x%llx\n", EmmcMmioBase)); + ControllerCount++; + } + } + + // Register SD controller if MMIO base is non-zero + if (SdMmioBase != 0) { + Status = RegisterNonDiscoverableMmioDevice ( + NonDiscoverableDeviceTypeSdhci, + NonDiscoverableDeviceDmaTypeCoherent, + NULL, + &mSdControllerHandle, + 1, + (UINTN)SdMmioBase, (UINTN)0x1000); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcMmioDxe: Failed to register SD controller: %r\n", Status)); + } else { + DEBUG ((DEBUG_INFO, "SdMmcMmioDxe: SD controller registered at 0x%llx\n", SdMmioBase)); + ControllerCount++; + } + } + + // Only install override protocol if at least one controller was registered + if (ControllerCount > 0) { + Handle = NULL; + Status = gBS->InstallProtocolInterface (&Handle, + &gEdkiiSdMmcOverrideProtocolGuid, + EFI_NATIVE_INTERFACE, (VOID **)&mSdMmcOverride); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SdMmcMmioDxe: Failed to install SD/MMC override protocol: %r\n", Status)); + return Status; + } + DEBUG ((DEBUG_INFO, "SdMmcMmioDxe: Registered %d controller(s)\n", ControllerCount)); + } else { + DEBUG ((DEBUG_WARN, "SdMmcMmioDxe: No controllers configured (both PCDs are 0)\n")); + } + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.dec b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.dec new file mode 100644 index 000000000000..9636c38c496b --- /dev/null +++ b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.dec @@ -0,0 +1,29 @@ +## @file +# +# Universal MMIO SDHCI eMMC/SD driver PCD definitions +# +# Copyright (c) 2024, CoolStar +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = SdMmcMmioDxe + PACKAGE_GUID = 4cd3a91b-990e-46a6-b609-9fa5d70d1f5f + PACKAGE_VERSION = 1.0 + +[PcdsFixedAtBuild] + ## MMIO base address for eMMC controller + # Set to 0 to disable eMMC controller registration + # Default: 0xFEDD5000 (AMD Picasso eMMC controller) + gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0xFEDD5000|UINT64|0x00000001 + + ## MMIO base address for SD controller + # Set to 0 to disable SD controller registration + # Default: 0 (disabled) + gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress|0x0|UINT64|0x00000002 + +[Guids] + gSdMmcMmioDxeTokenSpaceGuid = { 0x4cd3a91b, 0x990e, 0x46a6, { 0xb6, 0x09, 0x9f, 0xa5, 0xd7, 0x0d, 0x1f, 0x5f } } diff --git a/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.h b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.h new file mode 100644 index 000000000000..f5a5cf381e9d --- /dev/null +++ b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.h @@ -0,0 +1,65 @@ +/** @file + * + * Universal MMIO SDHCI eMMC/SD driver + * + * Copyright (c) 2022, Patrick Wildt + * Copyright (c) 2023, Mario Bălănică + * Copyright (c) 2024, CoolStar + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#ifndef __SDMMCMMIODXE_H__ +#define __SDMMCMMIODXE_H__ + +#include + +// PCD definitions for configurable MMIO base addresses +#define PCD_EMMC_MMIO_BASE_ADDRESS PcdGet64 (PcdEmmcMmioBaseAddress) +#define PCD_SD_MMIO_BASE_ADDRESS PcdGet64 (PcdSdMmioBaseAddress) + +typedef enum { + RemovableSlot, + EmbeddedSlot, + SharedBusSlot, + UnknownSlot +} EFI_SD_MMC_SLOT_TYPE; + +typedef struct { + UINT32 TimeoutFreq : 6; // bit 0:5 + UINT32 Reserved : 1; // bit 6 + UINT32 TimeoutUnit : 1; // bit 7 + UINT32 BaseClkFreq : 8; // bit 8:15 + UINT32 MaxBlkLen : 2; // bit 16:17 + UINT32 BusWidth8 : 1; // bit 18 + UINT32 Adma2 : 1; // bit 19 + UINT32 Reserved2 : 1; // bit 20 + UINT32 HighSpeed : 1; // bit 21 + UINT32 Sdma : 1; // bit 22 + UINT32 SuspRes : 1; // bit 23 + UINT32 Voltage33 : 1; // bit 24 + UINT32 Voltage30 : 1; // bit 25 + UINT32 Voltage18 : 1; // bit 26 + UINT32 SysBus64V4 : 1; // bit 27 + UINT32 SysBus64V3 : 1; // bit 28 + UINT32 AsyncInt : 1; // bit 29 + UINT32 SlotType : 2; // bit 30:31 + UINT32 Sdr50 : 1; // bit 32 + UINT32 Sdr104 : 1; // bit 33 + UINT32 Ddr50 : 1; // bit 34 + UINT32 Reserved3 : 1; // bit 35 + UINT32 DriverTypeA : 1; // bit 36 + UINT32 DriverTypeC : 1; // bit 37 + UINT32 DriverTypeD : 1; // bit 38 + UINT32 DriverType4 : 1; // bit 39 + UINT32 TimerCount : 4; // bit 40:43 + UINT32 Reserved4 : 1; // bit 44 + UINT32 TuningSDR50 : 1; // bit 45 + UINT32 RetuningMod : 2; // bit 46:47 + UINT32 ClkMultiplier : 8; // bit 48:55 + UINT32 Reserved5 : 7; // bit 56:62 + UINT32 Hs400 : 1; // bit 63 +} SD_MMC_HC_SLOT_CAP; + +#endif // __SDMMCMMIODXE_H__ diff --git a/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.inf b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.inf new file mode 100644 index 000000000000..3b61d80403e0 --- /dev/null +++ b/UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.inf @@ -0,0 +1,45 @@ +#/** @file +# +# Universal MMIO SDHCI eMMC/SD driver +# +# Copyright (c) 2014-2017, Linaro Limited. All rights reserved. +# Copyright (c) 2022, Patrick Wildt +# Copyright (c) 2023, Mario Bălănică +# Copyright (c) 2024, CoolStar +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = SdMmcMmioDxe + FILE_GUID = 4cd3a91b-990e-46a6-b609-9fa5d70d1f5f + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SdMmcMmioDxeInitialize + +[Sources.common] + SdMmcMmioDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + IoLib + PcdLib + NonDiscoverableDeviceRegistrationLib + UefiBootServicesTableLib + +[Protocols] + gEdkiiNonDiscoverableDeviceProtocolGuid ## PRODUCES + gEdkiiSdMmcOverrideProtocolGuid ## PRODUCES + gEfiCpuArchProtocolGuid + gEfiDevicePathProtocolGuid + +[Depex] + TRUE diff --git a/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.c b/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.c index d5406f0442b9..53d2557b57e3 100644 --- a/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.c +++ b/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.c @@ -174,7 +174,7 @@ SmmStoreInitialize ( EFI_PHYSICAL_ADDRESS MmioAddress; UINTN BlockSize; UINTN BlockCount; - UINT32 NvStorageBase; + UINT64 NvStorageBase; UINT32 NvStorageSize; UINT32 NvVariableSize; UINT32 FtwWorkingSize; @@ -225,26 +225,32 @@ SmmStoreInitialize ( FtwSpareSize = (BlockCount / 2) * BlockSize; FtwWorkingSize = 1 * BlockSize; NvVariableSize = NvStorageSize - FtwSpareSize - FtwWorkingSize; - DEBUG ((DEBUG_INFO, "NvStorageBase:0x%x, NvStorageSize:0x%x\n", NvStorageBase, NvStorageSize)); + DEBUG ((DEBUG_INFO, "NvStorageBase:0x%llx, NvStorageSize:0x%x\n", NvStorageBase, NvStorageSize)); Status = PcdSet32S (PcdFlashNvStorageVariableSize, NvVariableSize); ASSERT_EFI_ERROR (Status); - Status = PcdSet32S (PcdFlashNvStorageVariableBase, NvStorageBase); - ASSERT_EFI_ERROR (Status); + if (NvStorageBase < 0x100000000ULL) { + Status = PcdSet32S (PcdFlashNvStorageVariableBase, NvStorageBase); + ASSERT_EFI_ERROR (Status); + } Status = PcdSet64S (PcdFlashNvStorageVariableBase64, NvStorageBase); ASSERT_EFI_ERROR (Status); Status = PcdSet32S (PcdFlashNvStorageFtwWorkingSize, FtwWorkingSize); ASSERT_EFI_ERROR (Status); - Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, NvStorageBase + NvVariableSize); - ASSERT_EFI_ERROR (Status); + if ((NvStorageBase + NvVariableSize) < 0x100000000ULL) { + Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, NvStorageBase + NvVariableSize); + ASSERT_EFI_ERROR (Status); + } Status = PcdSet64S (PcdFlashNvStorageFtwWorkingBase64, NvStorageBase + NvVariableSize); ASSERT_EFI_ERROR (Status); Status = PcdSet32S (PcdFlashNvStorageFtwSpareSize, FtwSpareSize); ASSERT_EFI_ERROR (Status); - Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, NvStorageBase + NvVariableSize + FtwWorkingSize); - ASSERT_EFI_ERROR (Status); + if ((NvStorageBase + NvVariableSize + FtwWorkingSize) < 0x100000000ULL) { + Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, NvStorageBase + NvVariableSize + FtwWorkingSize); + ASSERT_EFI_ERROR (Status); + } Status = PcdSet64S (PcdFlashNvStorageFtwSpareBase64, NvStorageBase + NvVariableSize + FtwWorkingSize); ASSERT_EFI_ERROR (Status); diff --git a/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.c b/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.c index 63cb760d8c68..e156a89051bc 100644 --- a/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.c +++ b/UefiPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.c @@ -157,7 +157,7 @@ InitializeFvAndVariableStoreHeaders ( // Should be gEfiVariableGuid as SMM doesn't authenticate, but userspace does // Caveat: SecureBoot requires gEfiAuthenticatedVariableGuid type of storage // - CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid); + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid); VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength; VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED; VariableStoreHeader->State = VARIABLE_STORE_HEALTHY; diff --git a/UefiPayloadPkg/UefiPayloadEntry/AcpiTable.c b/UefiPayloadPkg/UefiPayloadEntry/AcpiTable.c index b50f460bb368..131bb958b290 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/AcpiTable.c +++ b/UefiPayloadPkg/UefiPayloadEntry/AcpiTable.c @@ -37,11 +37,16 @@ ParseAcpiInfo ( UINT32 *Signature; EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr; EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase; + UINTN TPM2TablePresent; + UINTN TCPATablePresent; Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase; DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp)); DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress)); + TPM2TablePresent = 0; + TCPATablePresent = 0; + // // Search Rsdt First // @@ -63,8 +68,16 @@ ParseAcpiInfo ( DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n")); } - if ((Fadt != NULL) && (MmCfgHdr != NULL)) { - goto Done; + if (*Signature == EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE) { + TPM2TablePresent = 1; + } + + if (*Signature == EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE) { + TCPATablePresent = 1; + } + + if ((Fadt != NULL) && (MmCfgHdr != NULL) && (TPM2TablePresent || TCPATablePresent )) { + goto TpmDectectDone; } } } @@ -88,8 +101,16 @@ ParseAcpiInfo ( DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n")); } - if ((Fadt != NULL) && (MmCfgHdr != NULL)) { - goto Done; + if (*Signature == EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE) { + TPM2TablePresent = 1; + } + + if (*Signature == EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE) { + TCPATablePresent = 1; + } + + if ((Fadt != NULL) && (MmCfgHdr != NULL) && (TPM2TablePresent || TCPATablePresent)) { + goto TpmDectectDone; } } } @@ -98,7 +119,10 @@ ParseAcpiInfo ( return RETURN_NOT_FOUND; } -Done: +TpmDectectDone: + + AcpiBoardInfo->TPM20Present = TPM2TablePresent; + AcpiBoardInfo->TPM12Present = TCPATablePresent; AcpiBoardInfo->PmCtrlRegBase = Fadt->Pm1aCntBlk; AcpiBoardInfo->PmTimerRegBase = Fadt->PmTmrBlk; @@ -124,6 +148,8 @@ ParseAcpiInfo ( DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase)); DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress)); DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize)); + DEBUG ((DEBUG_INFO, "TPM 2.0 present %x\n", AcpiBoardInfo->TPM20Present)); + DEBUG ((DEBUG_INFO, "TPM 1.2 present %x\n", AcpiBoardInfo->TPM12Present)); return RETURN_SUCCESS; } diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c index 468c36625c9a..d3ee18cc08c1 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c +++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c @@ -342,6 +342,8 @@ BuildHobFromBl ( ACPI_BOARD_INFO *AcpiBoardInfo; SMMSTORE_INFO SmmStoreInfo; SMMSTORE_INFO *NewSmmStoreInfo; + TCG_PHYSICAL_PRESENCE_INFO PhysicalPresenceInfo; + TCG_PHYSICAL_PRESENCE_INFO *NewPhysicalPresenceInfo; EFI_PEI_GRAPHICS_INFO_HOB GfxInfo; EFI_PEI_GRAPHICS_INFO_HOB *NewGfxInfo; EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo; @@ -399,6 +401,17 @@ BuildHobFromBl ( DEBUG ((DEBUG_INFO, "Created SmmStore info hob\n")); } + // + // Create guid hob for Tcg Physical Presence Interface + // + Status = ParseTPMPPIInfo (&PhysicalPresenceInfo); + if (!EFI_ERROR (Status)) { + NewPhysicalPresenceInfo = BuildGuidHob (&gEfiTcgPhysicalPresenceInfoHobGuid, sizeof (TCG_PHYSICAL_PRESENCE_INFO)); + ASSERT (NewPhysicalPresenceInfo != NULL); + CopyMem (NewPhysicalPresenceInfo, &PhysicalPresenceInfo, sizeof (TCG_PHYSICAL_PRESENCE_INFO)); + DEBUG ((DEBUG_INFO, "Created Tcg Physical Presence info hob\n")); + } + // // Create SmBios table Hob // diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h index b6fe5ef738f1..f48fd707e02b 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h +++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h @@ -39,6 +39,7 @@ #include #include #include +#include #define LEGACY_8259_MASK_REGISTER_MASTER 0x21 #define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1 diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf index 702be0d7a0d5..627bc67c0022 100644 --- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf +++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf @@ -72,6 +72,7 @@ gUniversalPayloadAcpiTableGuid gUniversalPayloadSerialPortInfoGuid gEfiSmmStoreInfoHobGuid + gEfiTcgPhysicalPresenceInfoHobGuid [FeaturePcd.IA32] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec index 491e5428b93a..e59bc210778a 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dec +++ b/UefiPayloadPkg/UefiPayloadPkg.dec @@ -19,6 +19,12 @@ [Guids] + # SMMSTORE for coreboot and EDK-2 + gEficorebootNvDataGuid = { 0xceae4c1d, 0x335b, 0x4685, { 0xa4, 0xa0, 0xfc, 0x4a, 0x94, 0xee, 0xa0, 0x85 } } + + # Bootloader option menu + gEfiCfrSetupMenuFormGuid = { 0xfbc3b1de, 0xd17c, 0x44de, { 0x98, 0x47, 0x2b, 0xbf, 0x9e, 0xfd, 0xbd, 0x8e } } + # ## Defines the token space for the UEFI Payload Package PCDs. # @@ -32,6 +38,12 @@ ## Include/UniversalPayload/DeviceTree.h gUniversalPayloadDeviceTreeGuid = { 0x6784b889, 0xb13c, 0x4c3b, {0xae, 0x4b, 0xf, 0xa, 0x2e, 0x32, 0xe, 0xa3 } } + + # + # Gop Temp + # + gBmpImageGuid = { 0x878AC2CC, 0x5343, 0x46F2, { 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } } + gEdkiiDebugPrintErrorLevelGuid = { 0xad82f436, 0x75c5, 0x4aa9, { 0x92, 0x93, 0xc5, 0x55, 0x0a, 0x7f, 0xf9, 0x71 }} gUefiAcpiBoardInfoGuid = {0xad3d31b, 0xb3d8, 0x4506, {0xae, 0x71, 0x2e, 0xf1, 0x10, 0x6, 0xd9, 0xf}} gUefiSerialPortInfoGuid = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1 } } @@ -46,6 +58,20 @@ gUplPciSegmentInfoHobGuid = {0x37e0e3a9, 0xb3fc, 0x4e85, { 0x97, 0x2b, 0x40, 0x82, 0xfc, 0x79, 0x40, 0x54 } } gEfiSmmStoreInfoHobGuid = { 0xf585ca19, 0x881b, 0x44fb, { 0x3f, 0x3d, 0x81, 0x89, 0x7c, 0x57, 0xbb, 0x01 } } + + gEfiTcgPhysicalPresenceInfoHobGuid = { 0xf367be59, 0x5891, 0x40eb, { 0x21, 0x44, 0xed, 0x2e, 0xac, 0x57, 0xfd, 0x14 }} + + # Secure Boot keys and owners + gMicrosoftVendorGuid = { 0x77fa9abd, 0x0359, 0x4d32, { 0xbd, 0x60, 0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b } } + gMicrosoftDbxUpdateGuid = { 0x4e52dd60, 0xd79e, 0x42c5, { 0x83, 0x37, 0x08, 0x92, 0x32, 0xea, 0x5c, 0x87 } } + gMicrosoftDbUefi2011Guid = { 0x73282f84, 0x7909, 0x4e87, { 0xad, 0xf0, 0x84, 0x5d, 0x5d, 0xa3, 0x35, 0xab } } + gMicrosoftDbWin2011Guid = { 0x9b29f606, 0x5102, 0x4de1, { 0xa8, 0x8a, 0xff, 0x62, 0x10, 0xbd, 0x8b, 0x65 } } + gMicrosoftDbUefi2023Guid = { 0xc7769261, 0xfe8d, 0x4e15, { 0xb3, 0x34, 0xca, 0xdf, 0x43, 0x64, 0xad, 0x92 } } + gMicrosoftDbWinUefi2023Guid = { 0x4ac66f32, 0x6895, 0x46fc, { 0xad, 0x00, 0xf1, 0xc8, 0x1d, 0x06, 0xc6, 0x68 } } + gMicrosoftKek2011Guid = { 0x73f89874, 0xb2ec, 0x4c28, { 0xa7, 0xe3, 0x7d, 0x80, 0x30, 0x13, 0x4e, 0x0b } } + gMicrosoftKek2023Guid = { 0xcce7d8e7, 0xaae8, 0x4697, { 0xb5, 0xc0, 0xef, 0x35, 0xa9, 0x2a, 0x05, 0x9f } } + gMicrosoftKekUefi2023Guid = { 0xf5a81b7b, 0x419a, 0x4a92, { 0x82, 0x12, 0x1c, 0x36, 0x9b, 0xcb, 0xe2, 0xcb } } + gMicrosoftPkOem2023Guid = { 0x701649dd, 0x8739, 0x40b9, { 0xbb, 0xdb, 0x9c, 0xa4, 0x34, 0xfd, 0xcd, 0x3b } } [Ppis] gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} } @@ -56,6 +82,10 @@ gUplReadyToPayloadPpiGuid = { 0x67c8dfb1, 0x61f4, 0x439c, { 0x84, 0x4e, 0x2b, 0xdf, 0xf1, 0x07, 0xad, 0x51 }} [Protocols] + # + # Gop Temp + # + gPlatformGOPPolicyGuid = { 0xec2e931b, 0x3281, 0x48a5, { 0x81, 0x07, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } } ################################################################################ # @@ -110,3 +140,7 @@ gUefiPayloadPkgTokenSpaceGuid.PcdFDTPageSize|8|UINT8|0x0000002C #- PcdUseUniversalPayloadSerialPort is TRUE, Serial Port parameters will be updated #- PcdUseUniversalPayloadSerialPort is FALSE, Serial Port parameters are fixed gUefiPayloadPkgTokenSpaceGuid.PcdUseUniversalPayloadSerialPort|TRUE|BOOLEAN|0x0000002D + +## PCDs for SdMmcMmioDxe +gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0x0000000000000000 |UINT64|0x0000002E +gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress |0x0000000000000000 |UINT64|0x0000002F diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 76e4e58f50a6..a1b0e29bdf2d 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -39,13 +39,17 @@ DEFINE ATA_ENABLE = TRUE DEFINE SD_ENABLE = TRUE DEFINE PS2_MOUSE_ENABLE = TRUE + DEFINE PRIORITIZE_INTERNAL = FALSE DEFINE SD_MMC_TIMEOUT = 1000000 DEFINE USE_CBMEM_FOR_CONSOLE = FALSE - DEFINE BOOTSPLASH_IMAGE = FALSE + DEFINE BOOTSPLASH_IMAGE = TRUE DEFINE NVME_ENABLE = TRUE + DEFINE UFS_ENABLE = FALSE DEFINE CAPSULE_SUPPORT = FALSE DEFINE LOCKBOX_SUPPORT = FALSE DEFINE LOAD_OPTION_ROMS = FALSE + DEFINE FOLLOW_BGRT_SPEC = FALSE + DEFINE USE_PCO_MMIO_EMMC = FALSE # # Crypto Support @@ -171,6 +175,36 @@ # HAND_OFF_FDT_ENABLE = FALSE + # Network definition + # + DEFINE NETWORK_ISCSI_ENABLE = FALSE + DEFINE NETWORK_PXE_BOOT = FALSE + DEFINE NETWORK_ENABLE = FALSE + DEFINE NETWORK_TLS_ENABLE = FALSE + DEFINE NETWORK_IP6_ENABLE = FALSE + DEFINE NETWORK_IP4_ENABLE = TRUE + DEFINE NETWORK_RTEK_PCI = FALSE + DEFINE NETWORK_RTEK_USB = FALSE + DEFINE NETWORK_ASIX_USB3 = FALSE + DEFINE NETWORK_ASIX_USB2 = FALSE + +!if $(NETWORK_PXE_BOOT) == TRUE + DEFINE NETWORK_SNP_ENABLE = TRUE + DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE +!else + DEFINE NETWORK_SNP_ENABLE = FALSE + DEFINE NETWORK_HTTP_BOOT_ENABLE = TRUE + DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE +!endif + +!include NetworkPkg/NetworkDefines.dsc.inc + + # Security options: + # + DEFINE TPM_ENABLE = TRUE + DEFINE TPM2_ENABLE = TRUE + DEFINE TPM1_ENABLE = TRUE + [BuildOptions] *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES !if $(USE_CBMEM_FOR_CONSOLE) == FALSE @@ -324,6 +358,7 @@ BlParseLib|UefiPayloadPkg/Library/SblParseLib/SblParseLib.inf !endif !endif + CfrHelpersLib|UefiPayloadPkg/Library/CfrHelpersLib/CfrHelpersLib.inf DebugLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf !if $(LOCKBOX_SUPPORT) == TRUE @@ -354,6 +389,13 @@ S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf !endif + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + +!include NetworkPkg/NetworkLibs.dsc.inc +!if $(NETWORK_TLS_ENABLE) == TRUE + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf +!endif + VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf @@ -391,6 +433,26 @@ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf +[LibraryClasses.common] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +!if $(TPM_ENABLE) == TRUE + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + TcgPhysicalPresenceLib|UefiPayloadPkg/Library/TcgPhysicalPresenceLibUefiPayload/DxeTcgPhysicalPresenceLib.inf + TcgPpVendorLib|SecurityPkg/Library/TcgPpVendorLibNull/TcgPpVendorLibNull.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + Tcg2PhysicalPresenceLib|UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresenceLib.inf + Tcg2PhysicalPresencePlatformLib|UefiPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf + Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf +!else + TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf + TcgPhysicalPresenceLib|UefiPayloadPkg/Library/TcgPhysicalPresenceLibNull/DxeTcgPhysicalPresenceLib.inf + Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf +!endif + [LibraryClasses.AARCH64] ArmHvcLib|ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf @@ -467,6 +529,22 @@ PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf !endif +!if $(SECURE_BOOT_ENABLE) == TRUE + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf + SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf + PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPolicy/PlatformPKProtectionLibVarPolicy.inf + + # re-use the UserPhysicalPresent() dummy implementation from the ovmf tree + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif + + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + [LibraryClasses.common.DXE_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf @@ -485,6 +563,29 @@ PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf !endif +!if $(SECURE_BOOT_ENABLE) == TRUE + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf + SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf + PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPolicy/PlatformPKProtectionLibVarPolicy.inf + + # re-use the UserPhysicalPresent() dummy implementation from the ovmf tree + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif + + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + + +!if $(TPM_ENABLE) == TRUE + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf +!endif + [LibraryClasses.common.DXE_RUNTIME_DRIVER] !if $(SECURE_BOOT_ENABLE) == TRUE BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf @@ -497,6 +598,18 @@ PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf !endif +!if $(SECURE_BOOT_ENABLE) == TRUE + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf + SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf + PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPolicy/PlatformPKProtectionLibVarPolicy.inf + + # re-use the UserPhysicalPresent() dummy implementation from the ovmf tree + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif + [LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf @@ -561,7 +674,7 @@ [PcdsFixedAtBuild] gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1 - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8000 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000 gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000 !if $(VARIABLE_SUPPORT) == "EMU" @@ -588,8 +701,16 @@ !endif gEfiMdeModulePkgTokenSpaceGuid.PcdSdMmcGenericTimeoutValue|$(SD_MMC_TIMEOUT) + gEfiMdeModulePkgTokenSpaceGuid.PcdPrioritizeInternal|$(PRIORITIZE_INTERNAL) + + # Universal MMIO SDHCI Driver PCDs + gSdMmcMmioDxeTokenSpaceGuid.PcdEmmcMmioBaseAddress|0xFEDD5000 + gSdMmcMmioDxeTokenSpaceGuid.PcdSdMmioBaseAddress|0x0 + gUefiPayloadPkgTokenSpaceGuid.PcdBootManagerEscape|$(BOOT_MANAGER_ESCAPE) + gEfiMdeModulePkgTokenSpaceGuid.PcdFollowBGRTSpecification|$(FOLLOW_BGRT_SPEC) + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1800000 !if $(CRYPTO_PROTOCOL_SUPPORT) == TRUE @@ -625,6 +746,14 @@ gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04 !endif + # Disable MTRR programming + gUefiCpuPkgTokenSpaceGuid.PcdCpuDisableMtrrProgramming|TRUE + + # Skip initializing CPU features during S3 resume for coreboot +!if $(BOOTLOADER) == COREBOOT + gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE +!endif + [PcdsFixedAtBuild.AARCH64] # System Memory Base -- fixed at 0x4000_0000 gArmTokenSpaceGuid.PcdSystemMemoryBase|0x40000000 @@ -675,9 +804,14 @@ gUefiPayloadPkgTokenSpaceGuid.PcdUseUniversalPayloadSerialPort|FALSE [PcdsPatchableInModule.IA32, PcdsPatchableInModule.X64] + + # + # Network Pcds + # !if $(NETWORK_DRIVER_ENABLE) == TRUE - gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections|TRUE + !include NetworkPkg/NetworkFixedPcds.dsc.inc !endif + gUefiPayloadPkgTokenSpaceGuid.SizeOfIoSpace|16 gUefiPayloadPkgTokenSpaceGuid.PcdFDTPageSize|8 # @@ -696,7 +830,7 @@ !if $(SOURCE_DEBUG_ENABLE) gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 !else - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xF !endif !else !if $(TARGET) == DEBUG @@ -800,6 +934,21 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0 gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE + ## Patched by BlSupportDxe + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy|0 + ## Match the hash algorithms listed in Tcg2Dxe + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap|0x1F + gEfiSecurityPkgTokenSpaceGuid.PcdTpmPhysicalPresence|TRUE + +!include NetworkPkg/NetworkDynamicPcds.dsc.inc + +[PcdsDynamicHii] +!if $(TPM2_ENABLE) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x0|"1.3"|NV,BS + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x8|4|NV,BS +!endif + [PcdsDynamicExDefault.IA32, PcdsDynamicExDefault.X64] gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister|$(RTC_INDEX_REGISTER) gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister|$(RTC_TARGET_REGISTER) @@ -929,19 +1078,34 @@ } !endif +!if $(NETWORK_DRIVER_ENABLE) == TRUE + # + # Rng Protocol producer + # + SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf + + # + # Hash2 Protocol producer + # + SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf +!endif + + !if $(SECURE_BOOT_ENABLE) == TRUE SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf !endif MdeModulePkg/Universal/BdsDxe/BdsDxe.inf !if $(BOOTSPLASH_IMAGE) MdeModulePkg/Logo/LogoDxe.inf !endif + UefiPayloadPkg/CfrSetupMenuDxe/CfrSetupMenuDxe.inf MdeModulePkg/Application/UiApp/UiApp.inf { - NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf + NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf } MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf @@ -1020,6 +1184,10 @@ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +!if $(UFS_ENABLE) == TRUE + MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf + MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf +!endif !if $(NVME_ENABLE) == TRUE MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf !endif @@ -1031,7 +1199,14 @@ # SD/eMMC Support # !if $(SD_ENABLE) == TRUE - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf + !if $(USE_PCO_MMIO_EMMC) == TRUE + MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf + UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.inf { + + NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf + } + !endif + UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.inf MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf !endif @@ -1079,7 +1254,13 @@ !if $(DISABLE_SERIAL_TERMINAL) == FALSE MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf !endif + +!if $(USE_PLATFORM_GOP) == TRUE + UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf +!else UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf +!endif + !if $(PERFORMANCE_MEASUREMENT_ENABLE) MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf !endif @@ -1135,6 +1316,46 @@ TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf } !endif +!endif + + # + # Network Support + # +!include NetworkPkg/NetworkComponents.dsc.inc + +!if $(NETWORK_TLS_ENABLE) == TRUE + NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf { + + NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf + } +!endif + +!if $(TPM_ENABLE) == TRUE + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf { + +# Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf //Modif H.E Avoid Hang Tcg2config + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf + } + SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { + + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + } + SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf { + + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf + } + !endif [Components.X64] @@ -1217,7 +1438,6 @@ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf - !include NetworkPkg/NetworkLibs.dsc.inc [Components.X64, Components.AARCH64] ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf { diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf index 334554a2508e..94f18eb16ee9 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.fdf +++ b/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -237,6 +237,52 @@ INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf !if $(UNIVERSAL_PAYLOAD) == FALSE !if $(SECURE_BOOT_ENABLE) == TRUE INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + INF UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf + + FILE FREEFORM = 4e52dd60-d79e-42c5-8337-089232ea5c87 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/dbx_microsoft_update.bin + SECTION UI = "Microsoft Corporation DBX Update" + } + + FILE FREEFORM = 73282f84-7909-4e87-adf0-845d5da335ab { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2011.der + SECTION UI = "Microsoft Corporation DB UEFI 2011" + } + + FILE FREEFORM = 9b29f606-5102-4de1-a88a-ff6210bd8b65 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_2011.der + SECTION UI = "Microsoft Corporation DB Windows 2011" + } + + FILE FREEFORM = c7769261-fe8d-4e15-b334-cadf4364ad92 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2023.der + SECTION UI = "Microsoft Corporation DB UEFI 2023" + } + + FILE FREEFORM = 4ac66f32-6895-46fc-ad00-f1c81d06c668 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_uefi_2023.der + SECTION UI = "Microsoft Corporation DB Windows UEFI 2023" + } + + FILE FREEFORM = 73f89874-b2ec-4c28-a7e3-7d8030134e0b { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2011.der + SECTION UI = "Microsoft Corporation KEK CA 2011" + } + + FILE FREEFORM = cce7d8e7-aae8-4697-b5c0-ef35a92a059f { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2023.der + SECTION UI = "Microsoft Corporation KEK CA 2023" + } + + FILE FREEFORM = f5a81b7b-419a-4a92-8212-1c369bcbe2cb { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_uefi_2023.der + SECTION UI = "Microsoft Corporation UEFI KEK CA 2023" + } + + FILE FREEFORM = 701649dd-8739-40b9-bbdb-9ca434fdcd3b { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/pk_microsoft_oem_2023.der + SECTION UI = "Microsoft Corporation OEM PK 2023" + } !endif !endif @@ -250,7 +296,7 @@ INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf -INF MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf +# INF MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf INF UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf @@ -290,7 +336,24 @@ INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf !if $(DISABLE_SERIAL_TERMINAL) == FALSE INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf !endif + +!if $(USE_PLATFORM_GOP) == TRUE +!if "X64" in $(ARCH) +INF UefiPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf +!endif +FILE DRIVER = FF0C8745-3270-4439-B74F-3E45F8C77064 { + SECTION DXE_DEPEX_EXP = {gPlatformGOPPolicyGuid} + SECTION PE32 = UefiPayloadPkg/IntelGopDriver.efi + SECTION UI = "IntelGopDriver" +} + +FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA { + SECTION RAW = UefiPayloadPkg/vbt.bin + SECTION UI = "IntelGopVbt" +} +!else INF UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf +!endif !if $(LOAD_OPTION_ROMS) == TRUE INF UefiPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf @@ -309,6 +372,14 @@ INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +!if $(UFS_ENABLE) == TRUE +INF MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf +INF MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf +FILE DRIVER = 700A8874-D215-4ACC-9EF2-7A80128560E0 { + SECTION PE32 = UefiPayloadPkg/UfsPlatform/UfsPlatform.efi + SECTION UI = "UfsPlatform" +} +!endif !if $(NVME_ENABLE) == TRUE INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf !endif @@ -317,15 +388,44 @@ INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf !endif INF FatPkg/EnhancedFatDxe/Fat.inf +# +# Filesystem drivers +# +!if $(ARCH) == IA32 +INF RuleOverride=BINARY USE = IA32 FSDrivers/exfat.inf +INF RuleOverride=BINARY USE = IA32 FSDrivers/ext2.inf +INF RuleOverride=BINARY USE = IA32 FSDrivers/ntfs.inf +INF RuleOverride=BINARY USE = IA32 FSDrivers/ext4.inf +!else +INF RuleOverride=BINARY USE = X64 FSDrivers/exfat.inf +INF RuleOverride=BINARY USE = X64 FSDrivers/ext2.inf +INF RuleOverride=BINARY USE = X64 FSDrivers/ntfs.inf +INF RuleOverride=BINARY USE = X64 FSDrivers/ext4.inf +!endif + # # SD/eMMC Support # !if $(SD_ENABLE) == TRUE -INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf +!if $(USE_PCO_MMIO_EMMC) == TRUE +INF MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf +INF UefiPayloadPkg/SdMmcMmioDxe/SdMmcMmioDxe.inf +!endif +INF UefiPayloadPkg/Bus/Pci/SdMmcPciCbDxe/SdMmcPciCbDxe.inf INF MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf INF MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf !endif +# +# TPM support +# +!if $(TPM_ENABLE) == TRUE +INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +INF SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf +INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf +!endif + # # Usb Support # @@ -348,6 +448,7 @@ INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResour !if $(UNIVERSAL_PAYLOAD) == FALSE INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +INF UefiPayloadPkg/CfrSetupMenuDxe/CfrSetupMenuDxe.inf INF RuleOverride = UI MdeModulePkg/Application/UiApp/UiApp.inf INF MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf # @@ -355,6 +456,46 @@ INF MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf # !if $(NETWORK_DRIVER_ENABLE) == TRUE !include NetworkPkg/Network.fdf.inc + # + # Rng Protocol producer + # + INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf + + # + # Hash2 Protocol producer + # + INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf +!endif +!endif + +# +# Network modules (only available on X64) +# Available at https://www.realtek.com and https://asix.com.tw +# +!if $(NETWORK_ENABLE) +!if $(ARCH) == IA32 + # FIXME +!else +!if $(NETWORK_RTEK_PCI) + FILE DRIVER = D30D5496-6DF9-462D-9B97-0B93F659D1A0 { + SECTION PE32 = UefiPayloadPkg/NetworkDrivers/RtkUndiDxe.efi + } +!endif +!if $(NETWORK_RTEK_USB) + FILE DRIVER = 95BA3BCA-F086-4FDA-BBAC-44F5AEE5176B { + SECTION PE32 = UefiPayloadPkg/NetworkDrivers/RtkUsbUndiDxe.efi + } +!endif +!if $(NETWORK_ASIX_USB3) + FILE DRIVER = 27E5D3B6-7839-47C2-8618-5D2190729BC7 { + SECTION PE32 = UefiPayloadPkg/NetworkDrivers/AX88179X_178A_772D_UEFI_v3.2.0_X64_signed.efi + } +!endif +!if $(NETWORK_ASIX_USB2) + FILE DRIVER = B15239D6-6A01-4808-A0F7-B7F20F073555 { + SECTION PE32 = UefiPayloadPkg/NetworkDrivers/AX88772C_772B_772A_UEFI_V2.8.0_X64.efi + } +!endif !endif !endif @@ -394,6 +535,52 @@ READ_LOCK_CAP = TRUE READ_LOCK_STATUS = TRUE INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +INF UefiPayloadPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf + +FILE FREEFORM = 4e52dd60-d79e-42c5-8337-089232ea5c87 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/dbx_microsoft_update.bin + SECTION UI = "Microsoft Corporation DBX Update" +} + +FILE FREEFORM = 73282f84-7909-4e87-adf0-845d5da335ab { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2011.der + SECTION UI = "Microsoft Corporation DB UEFI 2011" +} + +FILE FREEFORM = 9b29f606-5102-4de1-a88a-ff6210bd8b65 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_2011.der + SECTION UI = "Microsoft Corporation DB Windows 2011" +} + +FILE FREEFORM = c7769261-fe8d-4e15-b334-cadf4364ad92 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_uefi_2023.der + SECTION UI = "Microsoft Corporation DB UEFI 2023" +} + +FILE FREEFORM = 4ac66f32-6895-46fc-ad00-f1c81d06c668 { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/db_microsoft_win_uefi_2023.der + SECTION UI = "Microsoft Corporation DB Windows UEFI 2023" +} + +FILE FREEFORM = 73f89874-b2ec-4c28-a7e3-7d8030134e0b { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2011.der + SECTION UI = "Microsoft Corporation KEK CA 2011" +} + +FILE FREEFORM = cce7d8e7-aae8-4697-b5c0-ef35a92a059f { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_2023.der + SECTION UI = "Microsoft Corporation KEK CA 2023" +} + +FILE FREEFORM = f5a81b7b-419a-4a92-8212-1c369bcbe2cb { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/kek_microsoft_uefi_2023.der + SECTION UI = "Microsoft Corporation UEFI KEK CA 2023" +} + +FILE FREEFORM = 701649dd-8739-40b9-bbdb-9ca434fdcd3b { + SECTION RAW = UefiPayloadPkg/EnrollDefaultKeys/keys/pk_microsoft_oem_2023.der + SECTION UI = "Microsoft Corporation OEM PK 2023" +} !endif !endif diff --git a/UefiPayloadPkg/UfsPlatform/UfsPlatform.efi b/UefiPayloadPkg/UfsPlatform/UfsPlatform.efi new file mode 100644 index 000000000000..0a5e1db22c8e Binary files /dev/null and b/UefiPayloadPkg/UfsPlatform/UfsPlatform.efi differ