[
  {
    "path": ".gitignore",
    "content": "# Object files\n*.o\n*.ko\n*.obj\n*.elf\n*.bin\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n\n# Executables\n*.exe\n*.out\n*.app\n*.i*86\n*.x86_64\n*.hex\n*.map\n\n# Debug files\n*.dSYM/\n*.lst\n*.d\ntags\n\n#python compiled\n*.pyc\n\n#kconfig\nkconfig/.config\nkconfig/.config.old\nkconfig/.depend\n\n#generated files\napps/apps.ld\n.gdbinit\nbuild/\nkernel/syscall_table.c\n*.img\n*.ld\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"apps/busybox\"]\n\tpath = apps/busybox\n\turl = https://github.com/insane-adding-machines/busybox.git\n[submodule \"kernel/net/picotcp\"]\n\tpath = kernel/net/picotcp\n\turl = https://github.com/danielinux/picotcp.git\n[submodule \"frosted-userland\"]\n\tpath = frosted-userland\n\turl = https://github.com/insane-adding-machines/frosted-userland.git\n[submodule \"kernel/frosted-headers\"]\n\tpath = kernel/frosted-headers\n\turl = https://github.com/insane-adding-machines/frosted-headers.git\n[submodule \"kernel/unicore-mx\"]\n\tpath = kernel/unicore-mx\n\turl = https://github.com/insane-adding-machines/unicore-mx.git\n"
  },
  {
    "path": ".project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>Frosted</name>\n\t<comment></comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>\n\t\t\t<triggers>clean,full,incremental,</triggers>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>\n\t\t\t<triggers>full,incremental,</triggers>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t</buildSpec>\n\t<natures>\n\t\t<nature>org.eclipse.cdt.core.cnature</nature>\n\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\n\t\t<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>\n\t\t<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>\n\t</natures>\n</projectDescription>\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "Code of Conduct\n\nInsane-adding-machines is a community organization, whose purpose is to promote the use of Free Software in the Internet of things.\n\nWe value the involvement of everyone in this community. We are committed to creating a friendly and respectful place for learning, teaching and contributing. All participants in our events and communications are expected to show respect and courtesy to others.\n\nTo make clear what is expected, everyone participating in activities within Insane-adding-machines is required to conform to the following Code of Conduct. This code of conduct applies to all spaces managed by Insane-adding-machines including, but not limited to, workshops, email lists, online forums, IRC channels and on GitHub.\n\nCode of Conduct\n===============\n\nInsane-adding-machines are dedicated to providing a welcoming and supportive environment for all people, regardless of background or identity. However, we recognise that some groups in our community are subject to historical and ongoing discrimination, and may be vulnerable or disadvantaged. Membership in such a specific group can be on the basis of characteristics such as gender, sexual orientation, disability, physical appearance, body size, race, nationality, sex, colour, ethnic or social origin, pregnancy, citizenship, familial status, veteran status, genetic information, religion or belief, political or any other opinion, membership of a national minority, property, birth, age, or choice of text editor. We do not tolerate harassment of participants on the basis of these categories, or for any other reason.\n\nHarassment is any form of behaviour intended to exclude, intimidate, or cause discomfort. Because we are a diverse community, we may have different ways of communicating and of understanding the intent behind actions. Therefore we have chosen to prohibit certain forms of behaviour in our community, regardless of intent. Prohibited harassing behaviour includes but is not limited to:\n\n- written or verbal comments which have the effect of excluding people on the basis of membership of a specific group listed above\n    causing someone to fear for their safety, such as through stalking, following, or intimidation\n- the display of sexual or violent images\n- unwelcome sexual attention\n- nonconsensual or unwelcome physical contact\n- sustained disruption of talks, events or communications\n- incitement to violence, suicide, or self-harm\n- continuing to initiate interaction (including photography or recording) with someone after being asked to stop\n- publication of private communication without consent\n\nBehaviour not explicitly mentioned above may still constitute harassment. The list above should not be taken as exhaustive but rather as a guide to make it easier to enrich all of us and the communities in which we participate. All interactions should be professional regardless of location: harassment is prohibited whether it occurs on- or offline, and the same standards apply to both.\n\nEnforcement of the Code of Conduct will be respectful and not include any harassing behaviors.\n\nThank you for helping make this a welcoming, friendly community for all.\n\nThis code of conduct is a modified version of that used by PyCon, which in turn is forked from a template written by the Ada Initiative and hosted on the Geek Feminism Wiki. Contributors to this document: Adam Obeng, Aleksandra Pawlik, Bill Mills, Carol Willing, Erin Becker, Hilmar Lapp, Kara Woo, Karin Lagesen, Pauline Barmby, Sheila Miguez, Simon Waldman, Tracy Teal.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing to Frosted\n-----------------\n\nFrosted is a community project with no strong copyright enforcement.\nYou are free to contribute to the official repository, hosted at \ngithub.com/insane-adding-machines/frosted.\n\nBy contributing to Frosted, you agree that the code you write will be\npublished and distributed under the term of GNU General Public License,\nas specified in LICENSE.\n\nWe don't ask to yield any rights to the code you write, except those \nrequired by the LICENSE.\n\nIn order to contribute, fork the project on github, commit in your local repository, submit a PR.\nRegular contributors that show interest for the projects are added to the community.\n\nBeing part of the community means accepting the Code of Conduct.\n\nCoding style\n-----------------\n\n- Indentation is 4 spaces (no tabs)\n- no spaces inside parenthesis\n- spaces around binary operators\n- no trailing spaces\n- we place a space after every keyword\n- constants and macros are capitalized\n- the asterisk in a pointer declaration is adjacent to the symbol name, not its type\n- function opening brace is on the next line\n- inner blocks opening brace is on the same line\n- function/variable case default is `snake_case` and not `CamelCase`\n- no typedefs (exceptions must be discussed and approved by the community)\n- write short functions with meaningful names\n- centralized return point for functions is encouraged. The use of keyword `goto` is allowed to create a centralized return point.\n\nMore in general, we appreciate if you follow the same style as the existing kernel code.\n\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {description}\n    Copyright (C) {year}  {fullname}\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  {signature of Ty Coon}, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n\n"
  },
  {
    "path": "Makefile",
    "content": "-include kconfig/.config\nFROSTED:=$(PWD)\nFLASH_ORIGIN?=0x0\nCFLAGS+=-DFLASH_ORIGIN=$(FLASH_ORIGIN)\n\nifneq ($(V),1)\n   Q:=@\n   #Do not print \"Entering directory ...\".\n   MAKEFLAGS += --no-print-directory\nendif\n\n\n\n#kernel headers\nCFLAGS+=-Ikernel/frosted-headers/include -nostdlib\n\n#drivers headers\nCFLAGS+=-Ikernel/drivers\n\n#fs headers\nCFLAGS+=-Ikernel/fs\n\n# minimal kernel\nOBJS-y+= kernel/frosted.o \\\n\t\t kernel/vfs.o \\\n\t\t kernel/systick.o \\\n\t\t kernel/drivers/device.o \\\n\t\t kernel/mpu.o\t\t\t\t\\\n\t\t kernel/fpb.o\t\t\t\t\\\n\t\t kernel/string.o\t\t\t\\\n\t\t kernel/sys.o\t\t\t\t\\\n\t\t kernel/locks.o\t\t\t\t\\\n\t\t kernel/semaphore.o\t\t\t\\\n\t\t kernel/mutex.o\t\t\t\t\\\n\t\t kernel/tasklet.o\t\t\t\\\n\t\t kernel/scheduler.o\t\t\t\\\n\t\t kernel/syscall_table.o\t\t\\\n\t\t kernel/malloc.o\t\t\t\\\n\t\t kernel/module.o\t\t\t\\\n\t\t kernel/cirbuf.o\t\t\t\\\n\t\t kernel/term.o\t\t\t\t\\\n\t\t kernel/bflt.o\t\t\t\t\\\n\t\t kernel/getaddrinfo.o\t\t\\\n\t\t kernel/kprintf.o \t\t\t\\\n\t\t kernel/pipe.o\n\n\n-include rules/config.mk\ninclude  rules/arch.mk\ninclude  rules/picotcp.mk\ninclude  rules/userspace.mk\n\n\n# device drivers\n\nOBJS-$(ARCH_STM32F4)+=kernel/drivers/gpio.o \\\n\tkernel/drivers/exti.o\n\nOBJS-$(ARCH_STM32F7)+=kernel/drivers/gpio.o \\\n\tkernel/drivers/exti.o\n\nOBJS-$(ARCH_LPC17XX)+=kernel/drivers/gpio.o\nOBJS-$(ARCH_NRF51)+=kernel/drivers/gpio.o\nOBJS-$(ARCH_NRF52)+=kernel/drivers/gpio.o\n\nOBJS-$(MEMFS)+= kernel/fs/memfs.o\nOBJS-$(XIPFS)+= kernel/fs/xipfs.o\n\nCFLAGS-$(MEMFS)+=-DCONFIG_MEMFS\n\nOBJS-$(FATFS)+= kernel/fs/fatfs.o\nCFLAGS-$(FATFS)+=-DCONFIG_FATFS\nCFLAGS-$(FAT32)+=-DCONFIG_FAT32\n\nOBJS-$(SYSFS)+= kernel/fs/sysfs.o\nCFLAGS-$(SYSFS)+=-DCONFIG_SYSFS\n\nOBJS-$(DEVNULL)+= kernel/drivers/null.o\nCFLAGS-$(DEVNULL)+=-DCONFIG_DEVNULL\n\nOBJS-$(SOCK_UNIX)+= kernel/drivers/socket_un.o\nCFLAGS-$(SOCK_UNIX)+=-DCONFIG_SOCK_UNIX\n\nOBJS-$(PTY_UNIX)+= kernel/drivers/pty.o\nCFLAGS-$(PTY_UNIX)+=-DCONFIG_PTY_UNIX\n\nOBJS-$(PICOTCP)+= kernel/drivers/socket_in.o\nCFLAGS-$(PICOTCP)+=-DCONFIG_PICOTCP\nCFLAGS-$(CONFIG_PICOTCP_LOOP)+=\"-DCONFIG_PICOTCP_LOOP\"\n\nCFLAGS-$(TCPIP_MEMPOOL_YN)+=-DCONFIG_TCPIP_MEMPOOL=$(TCPIP_MEMPOOL)\n\nOBJS-$(DEVL3GD20)+= kernel/drivers/l3gd20.o\nCFLAGS-$(DEVL3GD20)+=-DCONFIG_DEVL3GD20\n\nOBJS-$(DEVLSM303DLHC)+= kernel/drivers/lsm303dlhc.o\nCFLAGS-$(DEVLSM303DLHC)+=-DCONFIG_DEVLSM303DLHC\n\nOBJS-$(DEVSTMPE811)+= kernel/drivers/stmpe811.o\nCFLAGS-$(DEVSTMPE811)+=-DCONFIG_DEVSTMPE811\n\nOBJS-$(DEVFT5336)+= kernel/drivers/ft5336.o\nCFLAGS-$(DEVFT5336)+=-DCONFIG_DEVFT5336\n\nOBJS-$(DEVMCCOG21)+= kernel/drivers/mccog21.o\nCFLAGS-$(DEVMCCOG21)+=-DCONFIG_DEVMCCOG21\n\nOBJS-$(DEVXALED5X7)+= kernel/drivers/xadow_LED_5x7.o\nCFLAGS-$(DEVXALED5X7)+=-DCONFIG_DEVXALED5X7\n\nOBJS-$(DEVSPI)+= kernel/drivers/stm32_spi.o\nCFLAGS-$(DEVSPI)+=-DCONFIG_DEVSTM32F4SPI\n\nOBJS-$(DEVLIS3DSH)+= kernel/drivers/lis3dsh.o\nCFLAGS-$(DEVLIS3DSH)+=-DCONFIG_DEVLIS3DSH\n\nOBJS-$(DEVSTM32I2C)+= kernel/drivers/stm32_i2c.o\nCFLAGS-$(DEVSTM32I2C)+=-DCONFIG_DEVI2C\n\nOBJS-$(DEVF4DSP)+=kernel/drivers/stm32f4_dsp.o\nCFLAGS-$(DEVF4DSP)+=-DCONFIG_DSP\n\nOBJS-$(DEVF4ETH)+= kernel/drivers/stm32_eth.o\nCFLAGS-$(DEVF4ETH)+=-DCONFIG_DEVETH\n\nOBJS-$(DEVF7ETH)+= kernel/drivers/stm32_eth.o\nCFLAGS-$(DEVF7ETH)+=-DCONFIG_DEVETH\n\nOBJS-$(DEVLM3SETH)+= kernel/drivers/lm3s_eth.o\nCFLAGS-$(DEVLM3SETH)+=-DCONFIG_DEVETH\n\nOBJS-$(DEVUART)+= kernel/drivers/uart.o\nCFLAGS-$(DEVUART)+=-DCONFIG_DEVUART\n\nOBJS-$(DEVILI9341)+= kernel/drivers/ili9341.o\nCFLAGS-$(DEVILI9341)+=-DCONFIG_DEVILI9341 -DCONFIG_LTDC\n\nOBJS-$(DEVF7DISCOLTDC) += kernel/drivers/stm32f7_ltdc.o\nCFLAGS-$(DEVF7DISCOLTDC)+=-DCONFIG_DEVF7DISCOLTDC -DCONFIG_LTDC\n\nOBJS-$(DEVFRAMEBUFFER)+= kernel/framebuffer.o\nCFLAGS-$(DEVFRAMEBUFFER)+=-DCONFIG_DEVFRAMEBUFFER \nOBJS-$(DEVFBCON)+= kernel/drivers/fbcon.o kernel/fonts/palette_256_xterm.o kernel/drivers/tty_console.o\nCFLAGS-$(DEVFBCON)+=-DCONFIG_DEVTTY_CONSOLE\n\n# Font Selection\nOBJS-$(FONT_CGA_8X8)+=kernel/fonts/cga_8x8.o\nCFLAGS-$(FONT_CGA_8X8)+=-DCONFIG_FONT_8x8\nOBJS-$(FONT_PICCOLO_7X6)+=kernel/fonts/piccolo_7x6.o\nCFLAGS-$(FONT_PICCOLO_7X6)+=-DCONFIG_FONT_7x6\n\nCFLAGS-$(DEVFBCON)+=-DCONFIG_DEVFBCON\n\nOBJS-$(DEVSTM32DMA)+=kernel/drivers/stm32_dma.o\nCFLAGS-$(DEVSTM32DMA)+=-DCONFIG_DMA\n\nCFLAGS-$(DEVSTM32USB)+=-DCONFIG_DEVUSB\nOBJS-$(DEVSTM32USB)+=kernel/drivers/stm32_usb.o\nCFLAGS-$(DEVSTM32USBFS)+=-DCONFIG_DEVUSBFS\nCFLAGS-$(DEVSTM32USBHS)+=-DCONFIG_DEVUSBHS\n\nCFLAGS-$(USBFS_HOST)+=-DCONFIG_USBHOST -DCONFIG_USBFSHOST\nCFLAGS-$(USBHS_HOST)+=-DCONFIG_USBHOST -DCONFIG_USBHSHOST\n\nOBJS-$(DEVSTM32SDIO)+=kernel/drivers/stm32_sdio.o\nCFLAGS-$(DEVSTM32SDIO)+=-DCONFIG_SDIO\n\nOBJS-$(LOWPOWER)+=kernel/drivers/stm32_lowpower.o\nCFLAGS-$(LSE32K)+=-DCONFIG_LSE32K\n\nOBJS-$(DEVADC)+=kernel/drivers/stm32f4_adc.o\nCFLAGS-$(DEVADC)+=-DCONFIG_DEVADC\n\nOBJS-$(DEVRNG)+=kernel/drivers/stm32_rng.o\nCFLAGS-$(DEVRNG)+=-DCONFIG_RNG\n\nOBJS-$(DEVFRAND)+=kernel/drivers/stm32_rng.o\t\t\\\n\t\t kernel/crypto/misc.o\t\t\t\\\n\t\t kernel/crypto/sha256.o\t\t\t\\\n\t\t kernel/crypto/aes.o\t\t\t\\\n\t\t kernel/drivers/fortuna.o\t\t\\\n\t\t kernel/drivers/frand.o\nCFLAGS-$(DEVFRAND)+=-DCONFIG_FRAND -DCONFIG_RNG\nOBJS-$(STM32F7_SDRAM)+=kernel/drivers/stm32f7_sdram.o\nOBJS-$(STM32F4_SDRAM)+=kernel/drivers/stm32f4_sdram.o\nCFLAGS-$(STM32F7_SDRAM)+=-DCONFIG_SDRAM\nCFLAGS-$(STM32F4_SDRAM)+=-DCONFIG_SDRAM\n\nOBJS-$(DEV_USB_ETH)+=kernel/drivers/devusb_cdc_ecm.o\nCFLAGS-$(DEV_USB_ETH)+=-DCONFIG_DEV_USBETH\nCFLAGS-$(DEV_USB_ETH)+=-DCONFIG_USB_DEFAULT_IP=\\\"$(USB_DEFAULT_IP)\\\"\nCFLAGS-$(DEV_USB_ETH)+=-DCONFIG_USB_DEFAULT_NM=\\\"$(USB_DEFAULT_NM)\\\"\nCFLAGS-$(DEV_USB_ETH)+=-DCONFIG_USB_DEFAULT_GW=\\\"$(USB_DEFAULT_GW)\\\"\n\n\nOBJS-$(DEV_USBH_KBD)+=kernel/drivers/usb/usb_kbd.o\nCFLAGS-$(DEV_USBH_KBD)+=-DCONFIG_DEV_USBH_KBD\n\nCFLAGS-$(DEVF4ETH)+=-DCONFIG_DEV_ETH\nCFLAGS-$(DEVF4ETH)+=-DCONFIG_ETH_DEFAULT_IP=\\\"$(ETH_DEFAULT_IP)\\\"\nCFLAGS-$(DEVF4ETH)+=-DCONFIG_ETH_DEFAULT_NM=\\\"$(ETH_DEFAULT_NM)\\\"\nCFLAGS-$(DEVF4ETH)+=-DCONFIG_ETH_DEFAULT_GW=\\\"$(ETH_DEFAULT_GW)\\\"\nCFLAGS-$(DEVF7ETH)+=-DCONFIG_DEV_ETH\nCFLAGS-$(DEVF7ETH)+=-DCONFIG_ETH_DEFAULT_IP=\\\"$(ETH_DEFAULT_IP)\\\"\nCFLAGS-$(DEVF7ETH)+=-DCONFIG_ETH_DEFAULT_NM=\\\"$(ETH_DEFAULT_NM)\\\"\nCFLAGS-$(DEVF7ETH)+=-DCONFIG_ETH_DEFAULT_GW=\\\"$(ETH_DEFAULT_GW)\\\"\nCFLAGS-$(DEVLM3SETH)+=-DCONFIG_DEV_ETH\nCFLAGS-$(DEVLM3SETH)+=-DCONFIG_ETH_DEFAULT_IP=\\\"$(ETH_DEFAULT_IP)\\\"\nCFLAGS-$(DEVLM3SETH)+=-DCONFIG_ETH_DEFAULT_NM=\\\"$(ETH_DEFAULT_NM)\\\"\nCFLAGS-$(DEVLM3SETH)+=-DCONFIG_ETH_DEFAULT_GW=\\\"$(ETH_DEFAULT_GW)\\\"\n\nOBJS-$(MACH_STM32F407Discovery)+=kernel/$(BOARD)/stm32f407discovery.o\nCFLAGS-$(MACH_STM32F405Pyboard10)+=-DCONFIG_PYBOARD_1_0\nCFLAGS-$(MACH_STM32F405Pyboard11)+=-DCONFIG_PYBOARD_1_1 -DCLOCK_12MHZ\nCFLAGS-$(MACH_STM32F411Pyboard11lite)+=-DCONFIG_PYBOARD_1_1 -DCLOCK_12MHZ\nOBJS-$(MACH_STM32F405Pyboard10)+=kernel/$(BOARD)/stm32f4xxpyboard.o\nOBJS-$(MACH_STM32F405Pyboard11)+=kernel/$(BOARD)/stm32f4xxpyboard.o\nOBJS-$(MACH_STM32F411Pyboard11lite)+=kernel/$(BOARD)/stm32f4xxpyboard.o\nOBJS-$(MACH_STM32F411Nucleo)+=kernel/$(BOARD)/stm32f411nucleo.o\nOBJS-$(MACH_STM32F4x1Discovery)+=kernel/$(BOARD)/stm32f4x1discovery.o\nOBJS-$(MACH_STM32F429Discovery)+=kernel/$(BOARD)/stm32f429discovery.o\nOBJS-$(MACH_STM32F446Nucleo)+=kernel/$(BOARD)/stm32f446nucleo.o\nOBJS-$(MACH_STM32F746Discovery)+=kernel/$(BOARD)/stm32f746discovery.o\nOBJS-$(MACH_STM32F769Discovery)+=kernel/$(BOARD)/stm32f769discovery.o\nOBJS-$(MACH_STM32F746Nucleo144)+=kernel/$(BOARD)/stm32f746nucleo-144.o\nOBJS-$(MACH_LPC1768MBED)+=kernel/$(BOARD)/lpc1768mbed.o\nOBJS-$(MACH_SEEEDPRO)+=kernel/$(BOARD)/lpc1768mbed.o\nOBJS-$(MACH_LPC1679XPRESSO)+=kernel/$(BOARD)/lpc1769xpresso.o\nOBJS-$(MACH_LM3S6965EVB)+=kernel/$(BOARD)/lm3s6965evb.o\nOBJS-$(MACH_LM3SVIRT)+=kernel/$(BOARD)/lm3s6965evb.o\nOBJS-$(MACH_BLENANOV1_5)+=kernel/$(BOARD)/blenanov1_5.o\nOBJS-$(MACH_BLENANOV2_0)+=kernel/$(BOARD)/blenanov2_0.o\nOBJS-$(MACH_STM32F407Diymore)+=kernel/$(BOARD)/stm32f407diymore.o\n\n\nLIB-y:=\nLIB-$(PICOTCP)+=$(PREFIX)/lib/libpicotcp.a\nLIB-y+=kernel/unicore-mx/lib/libucmx_$(BOARD).a\nOBJS-$(PICOTCP)+=kernel/net/pico_lock.o\n\nCFLAGS+=$(CFLAGS-y)\n\nSHELL=/bin/bash\nall: image.bin\n\nkernel/syscall_table.c: kernel/syscall_table_gen.py\n\t@python2 $^\n\n$(PREFIX)/lib/libpicotcp.a:\n\techo $(BUILD_PICO)\n\t$(BUILD_PICO)\n\t@pwd\n\n.PHONY: FORCE st-flash\n\nst-flash: image.bin\n\tst-flash write image.bin 0x08000000\n\nkernel.img: kernel.elf\n\t@export PADTO=`python2 -c \"print ( $(KFLASHMEM_SIZE) * 1024) + int('$(FLASH_ORIGIN)', 16)\"`;\t\\\n\t$(CROSS_COMPILE)objcopy -O binary --pad-to=$$PADTO kernel.elf $@\n\napps.img: $(USERSPACE)\n\t@make -C $(USERSPACE) FROSTED=$(PWD) FAMILY=$(FAMILY) ARCH=$(MCPU)\n\nimage.bin: kernel.img apps.img\n\tcat kernel.img apps.img > $@\n\nkernel/unicore-mx/lib/libucmx_$(BOARD).a:\n\tmake -C kernel/unicore-mx FP_FLAGS=\"-mfloat-abi=soft\" PREFIX=arm-frosted-eabi TARGETS=$(UNICOREMX_TARGET)\n\nkernel/$(BOARD)/$(BOARD).ld: kernel/$(BOARD)/$(BOARD).ld.in\n\texport KRAMMEM_SIZE_B=`python2 -c \"print '0x%X' % ( $(KRAMMEM_SIZE) * 1024)\"`;\t\\\n\texport KFLASHMEM_SIZE_B=`python2 -c \"print '0x%X' % ( $(KFLASHMEM_SIZE) * 1024)\"`;\t\\\n\texport RAM1_SIZE_B=`python2 -c \"print '0x%X' % ( $(RAM1_SIZE) * 1024)\"`;\t\\\n\texport RAM2_SIZE_B=`python2 -c \"print '0x%X' % ( $(RAM2_SIZE) * 1024)\"`;\t\\\n\texport RAM3_SIZE_B=`python2 -c \"print '0x%X' % ( $(RAM3_SIZE) * 1024)\"`;\t\\\n\texport SDRAM_SIZE_B=`python2 -c \"print '0x%X' % ( $(SDRAM_SIZE))\"`;\t\\\n\tcat $^ | sed -e \"s/__FLASH_ORIGIN/$(FLASH_ORIGIN)/g\" | \\\n\t\t\t sed -e \"s/__KFLASHMEM_SIZE/$$KFLASHMEM_SIZE_B/g\" | \\\n\t\t\t sed -e \"s/__KRAMMEM_SIZE/$$KRAMMEM_SIZE_B/g\" |\\\n\t\t\t sed -e \"s/__RAM1_BASE/$(RAM1_BASE)/g\" |\\\n\t\t\t sed -e \"s/__RAM2_BASE/$(RAM2_BASE)/g\" |\\\n\t\t\t sed -e \"s/__RAM3_BASE/$(RAM3_BASE)/g\" |\\\n\t\t\t sed -e \"s/__SDRAM_BASE/$(SDRAM_BASE)/g\" |\\\n\t\t\t sed -e \"s/__RAM1_SIZE/$$RAM1_SIZE_B/g\" |\\\n\t\t\t sed -e \"s/__RAM2_SIZE/$$RAM2_SIZE_B/g\" |\\\n\t\t\t sed -e \"s/__RAM3_SIZE/$$RAM3_SIZE_B/g\" |\\\n\t\t\t sed -e \"s/__SDRAM_SIZE/$$SDRAM_SIZE_B/g\" \\\n\t\t\t >$@\n\nkernel.elf: $(LIB-y) $(OBJS-y) kernel/$(BOARD)/$(BOARD).ld\n\t@$(CC) -o $@   -Tkernel/$(BOARD)/$(BOARD).ld -Wl,--start-group $(OBJS-y) $(LIB-y) -Wl,--end-group \\\n\t\t-Wl,-Map,kernel.map  $(LDFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)\n\n\n\nqemudbg: image.bin\n\tqemu-system-arm -M lm3s6965evb --kernel image.bin -nographic -S -gdb tcp::3333\n\nqemu: image.bin\n\tqemu-system-arm -M lm3s6965evb --kernel image.bin -nographic\n\nqemu2: qemu\n\nqemunet:\n\tsudo qemu-system-arm -M lm3s6965evb --kernel image.bin -nographic -net nic,vlan=0 -net tap,vlan=0,ifname=frost0\n\nqemunetdbg:\n\tsudo qemu-system-arm -M lm3s6965evb --kernel image.bin -nographic -S -gdb tcp::3333 -net nic,vlan=0 -net tap,vlan=0,ifname=frost0\n\nqemubridgedbg:\n\tqemu-system-arm -M lm3s6965evb --kernel image.bin -nographic -S -gdb tcp::3333 -net nic,vlan=0 -net tap,helper=$(HOME)/frosted-qemu/qemu-bin/libexec/qemu-bridge-helper\n\nqemubridge:\n\tqemu-system-arm -M lm3s6965evb --kernel image.bin -nographic -net nic,vlan=0 -net tap,helper=$(HOME)/frosted-qemu/qemu-bin/libexec/qemu-bridge-helper\n\nmenuconfig:\n\t@$(MAKE) -C kconfig/ menuconfig -f Makefile.frosted\n\nconfig:\n\t@$(MAKE) -C kconfig/ config -f Makefile.frosted\n\ndefconfig: FORCE\n\t@test $(TARGET) || (echo \"ERROR: you must define a target\" && false)\n\t@cp -i defconfig/$(TARGET).config kconfig/.config\n\nmalloc_test:\n\t@gcc -o malloc.test kernel/malloc.c -DCONFIG_KRAM_SIZE=4\n\n\nlibclean: clean\n\t@make -C kernel/unicore-mx clean PREFIX=arm-frosted-eabi\n\nclean:\n\t@rm -f malloc.test\n\t@rm -f  kernel/$(BOARD)/$(BOARD).ld\n\t@make -C $(USERSPACE) clean\n\t@rm -f $(OBJS-y)\n\t@rm -f *.map *.bin *.elf *.img\n\t@rm -f kernel/$(BOARD)/$(BOARD).ld\n\t@rm -rf build\n\t@rm -f tags\n\t@rm -f kernel/syscall_table.c\n"
  },
  {
    "path": "README.md",
    "content": "# Frosted :snowman:\n\n## We moved to gitlab!\n\nPlease visit [Frosted OS](https://gitlab.com/insane-adding-machines/frosted) and [Insane Adding Machines](https://gitlab.com/insane-adding-machines/) new homes!\n\nBye!\n\n_the frosted development team_\n"
  },
  {
    "path": "defconfig/lpc1769.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\nARCH_LPC17XX=y\n# ARCH_STM32F4 is not set\n# ARCH_STM32F7 is not set\n# ARCH_LPC1763 is not set\n# ARCH_LPC1764 is not set\n# ARCH_LPC1765 is not set\n# ARCH_LPC1766 is not set\n# ARCH_LPC1767 is not set\n# ARCH_LPC1768 is not set\nARCH_LPC1769=y\nFLASH_SIZE_512KB=y\nRAM_SIZE_32KB=y\n# CLK_100MHZ is not set\nCLK_120MHZ=y\nMACH_LPC1679XPRESSO=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=128\nKRAMMEM_SIZE=32\n# TASK_STACK_SIZE_1K is not set\nTASK_STACK_SIZE_2K=y\n# TASK_STACK_SIZE_4K is not set\n# TASK_STACK_SIZE_8K is not set\nMPU=y\nPTHREADS=y\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\nSTRACE=y\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\n# SOCK_INET is not set\n# TCPIP_MEMPOOL_YN is not set\n\n#\n# Device Drivers\n#\n# DEVNULL is not set\nDEVUART=y\nUART_0=y\n# UART_1 is not set\n# UART_2 is not set\n# UART_3 is not set\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/lpc17xx.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\nARCH_LPC17XX=y\n# ARCH_STM32F4 is not set\n# ARCH_STM32F7 is not set\n# ARCH_LPC1763 is not set\n# ARCH_LPC1764 is not set\n# ARCH_LPC1765 is not set\n# ARCH_LPC1766 is not set\n# ARCH_LPC1767 is not set\nARCH_LPC1768=y\n# ARCH_LPC1769 is not set\nFLASH_SIZE_512KB=y\nRAM_SIZE_32KB=y\nCLK_100MHZ=y\n# MACH_LPC1768MBED is not set\nMACH_SEEEDPRO=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=128\nKRAMMEM_SIZE=32\n\n#\n# IPC features\n#\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\nSTRACE=y\n# TASK_STACK_SIZE_1K is not set\nTASK_STACK_SIZE_2K=y\n# TASK_STACK_SIZE_4K is not set\n# TASK_STACK_SIZE_8K is not set\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\n# SOCK_INET is not set\n# TCPIP_MEMPOOL_YN is not set\n\n#\n# Device Drivers\n#\n# DEVNULL is not set\nDEVUART=y\nUART_0=y\n# UART_1 is not set\n# UART_2 is not set\n# UART_3 is not set\nDEVGPIO=y\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/qemu-orig.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\nARCH_LM3S=y\n# ARCH_LPC17XX is not set\n# ARCH_STM32F4 is not set\n# ARCH_STM32F7 is not set\nARCH_LM3S6965=y\n# ARCH_LM3SVIRT is not set\nFLASH_SIZE_256KB=y\nRAM_SIZE_64KB=y\nMACH_LM3S6965EVB=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=64\nKRAMMEM_SIZE=32\n# TASK_STACK_SIZE_1K is not set\nTASK_STACK_SIZE_2K=y\n# TASK_STACK_SIZE_4K is not set\n# TASK_STACK_SIZE_8K is not set\nMPU=y\n\n#\n# IPC features\n#\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\n# STRACE is not set\n\n#\n# Filesystems\n#\nSYSFS=y\n# MEMFS is not set\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\n# SOCK_INET is not set\n# TCPIP_MEMPOOL_YN is not set\n\n#\n# Device Drivers\n#\n# DEVNULL is not set\nDEVUART=y\nUSART_0=y\n# USART_1 is not set\n# USART_2 is not set\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/qemu.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\nARCH_LM3S=y\n# ARCH_LPC17XX is not set\n# ARCH_STM32F4 is not set\n# ARCH_STM32F7 is not set\n# ARCH_LM3S6965 is not set\nARCH_LM3SVIRT=y\nFLASH_SIZE_1MB=y\nRAM_SIZE_256KB=y\nMACH_LM3SVIRT=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=128\nKRAMMEM_SIZE=128\n# TASK_STACK_SIZE_1K is not set\n# TASK_STACK_SIZE_2K is not set\nTASK_STACK_SIZE_4K=y\n# TASK_STACK_SIZE_8K is not set\nMPU=y\nPTHREADS=y\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\n# STRACE is not set\n\n#\n# Filesystems\n#\nSYSFS=y\n# MEMFS is not set\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\n# SOCK_INET is not set\n# TCPIP_MEMPOOL_YN is not set\n\n#\n# Device Drivers\n#\nDEVNULL=y\nDEVUART=y\nUSART_0=y\n# USART_1 is not set\n# USART_2 is not set\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/qemunet.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\nARCH_LM3S=y\n# ARCH_LPC17XX is not set\n# ARCH_STM32F4 is not set\n# ARCH_STM32F7 is not set\n# ARCH_LM3S6965 is not set\nARCH_LM3SVIRT=y\nFLASH_SIZE_1MB=y\nRAM_SIZE_256KB=y\nMACH_LM3SVIRT=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=128\nKRAMMEM_SIZE=64\n# TASK_STACK_SIZE_1K is not set\nTASK_STACK_SIZE_2K=y\n# TASK_STACK_SIZE_4K is not set\n# TASK_STACK_SIZE_8K is not set\nMPU=y\nPTHREADS=y\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\n# STRACE is not set\n\n#\n# Filesystems\n#\nSYSFS=y\n# MEMFS is not set\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\nSOCK_INET=y\n# TCPIP_MEMPOOL_YN is not set\nPICOTCP=y\n\n#\n# picoTCP configuration\n#\nCONFIG_PICOTCP_IPV4=y\n# CONFIG_PICOTCP_IPV6 is not set\nCONFIG_PICOTCP_TCP=y\nCONFIG_PICOTCP_UDP=y\nCONFIG_PICOTCP_DNS=y\n# CONFIG_PICOTCP_MCAST is not set\n# CONFIG_PICOTCP_NAT is not set\n# CONFIG_PICOTCP_IPFILTER is not set\nCONFIG_PICOTCP_LOOP=y\n# CONFIG_PICOTCP_DEBUG is not set\n\n#\n# Device Drivers\n#\nDEVNULL=y\nDEVUART=y\nUSART_0=y\n# USART_1 is not set\n# USART_2 is not set\nDEVLM3SETH=y\nETH_DEFAULT_IP=\"192.168.20.150\"\nETH_DEFAULT_NM=\"255.255.255.0\"\nETH_DEFAULT_GW=\"192.168.20.1\"\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/stm32f407-discovery.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\n# ARCH_LPC17XX is not set\nARCH_STM32F4=y\n# ARCH_STM32F7 is not set\n# ARCH_STM32F401_XB is not set\n# ARCH_STM32F401_XC is not set\n# ARCH_STM32F401_XD is not set\n# ARCH_STM32F401_XE is not set\n# ARCH_STM32F405_XG is not set\n# ARCH_STM32F405_XE is not set\nARCH_STM32F407_XG=y\n# ARCH_STM32F407_XE is not set\n# ARCH_STM32F411_XE is not set\n# ARCH_STM32F411_XC is not set\n# ARCH_STM32F429_XE is not set\n# ARCH_STM32F429_XG is not set\n# ARCH_STM32F429_XI is not set\n# ARCH_STM32F446_ZE is not set\nFLASH_SIZE_1MB=y\nRAM_SIZE_192KB=y\nARCH_STM32F407=y\nDEVSTM32DMA=y\n# CLK_120MHZ is not set\nCLK_168MHZ=y\nMACH_STM32F407Discovery=y\n# STM32F4_SDRAM is not set\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=192\nKRAMMEM_SIZE=128\n# TASK_STACK_SIZE_1K is not set\n# TASK_STACK_SIZE_2K is not set\nTASK_STACK_SIZE_4K=y\n# TASK_STACK_SIZE_8K is not set\nMPU=y\nPTHREADS=y\nSIGNALS=y\nPIPE=y\nSOCK_UNIX=y\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\n# STRACE is not set\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\n# SOCK_INET is not set\n# TCPIP_MEMPOOL_YN is not set\n\n#\n# Device Drivers\n#\nDEVNULL=y\nDEVUART=y\n# USART_1 is not set\nUSART_2=y\n# USART_3 is not set\n# USART_6 is not set\nDEVF4DSP=y\nDEVSTM32USB=y\nDEVSTM32USBFS=y\nUSBFS_HOST=y\n# USBFS_GUEST is not set\n# DEVTIM is not set\n# DEVADC is not set\n# DEVSTM32SDIO is not set\n# DEVSTM32I2C is not set\n# DEVSPI is not set\n# DEV_RANDOM is not set\n# DEVFRAMEBUFFER is not set\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/stm32f429i-discovery.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\n# ARCH_LPC17XX is not set\nARCH_STM32F4=y\n# ARCH_STM32F7 is not set\n# ARCH_STM32F401_XB is not set\n# ARCH_STM32F401_XC is not set\n# ARCH_STM32F401_XD is not set\n# ARCH_STM32F401_XE is not set\n# ARCH_STM32F405_XG is not set\n# ARCH_STM32F405_XE is not set\n# ARCH_STM32F407_XG is not set\n# ARCH_STM32F407_XE is not set\n# ARCH_STM32F411_XE is not set\n# ARCH_STM32F411_XC is not set\n# ARCH_STM32F429_XE is not set\n# ARCH_STM32F429_XG is not set\nARCH_STM32F429_XI=y\n# ARCH_STM32F446_ZE is not set\nFLASH_SIZE_2MB=y\nRAM_SIZE_256KB=y\nARCH_STM32F429=y\n# CLK_48MHZ is not set\n# CLK_84MHZ is not set\nCLK_168MHZ=y\nMACH_STM32F429Discovery=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=128\nKRAMMEM_SIZE=64\n# TASK_STACK_SIZE_1K is not set\nTASK_STACK_SIZE_2K=y\n# TASK_STACK_SIZE_4K is not set\n# TASK_STACK_SIZE_8K is not set\nMPU=y\n\n#\n# IPC features\n#\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\nKLOG=y\nKLOG_SIZE=256\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\n# STRACE is not set\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\n# SOCK_INET is not set\n# TCPIP_MEMPOOL_YN is not set\n\n#\n# Device Drivers\n#\nDEVNULL=y\nDEVUART=y\nUSART_1=y\n# USART_2 is not set\n# DEVF4DSP is not set\n# DEVSTM32USB is not set\n# DEVTIM is not set\n# DEVADC is not set\n# DEVSTM32SDIO is not set\n# DEVSTM32I2C is not set\n# DEVSPI is not set\n# DEV_RANDOM is not set\n# DEVRNG is not set\n# DEVFRAND is not set\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/stm32f746-discovery.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\n# ARCH_LPC17XX is not set\n# ARCH_STM32F4 is not set\nARCH_STM32F7=y\nARCH_STM32F746_NG=y\n# ARCH_STM32F769_NI is not set\nFLASH_SIZE_1MB=y\nRAM_SIZE_320KB=y\nARCH_STM32F746=y\nCLK_216MHZ=y\nMACH_STM32F746Discovery=y\n# MACH_STM32F746Nucleo144 is not set\nSTM32F7_SDRAM=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=256\nKRAMMEM_SIZE=256\n# TASK_STACK_SIZE_1K is not set\n# TASK_STACK_SIZE_2K is not set\nTASK_STACK_SIZE_4K=y\n# TASK_STACK_SIZE_8K is not set\nMPU=y\nPTHREADS=y\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\nSTRACE=y\n\n#\n# Filesystems\n#\nSYSFS=y\n# MEMFS is not set\nXIPFS=y\nFATFS=y\nFAT32=y\nFAT16=y\n\n#\n# Networking\n#\nSOCK_INET=y\n# TCPIP_MEMPOOL_YN is not set\nPICOTCP=y\n\n#\n# picoTCP configuration\n#\nCONFIG_PICOTCP_IPV4=y\n# CONFIG_PICOTCP_IPV6 is not set\nCONFIG_PICOTCP_TCP=y\nCONFIG_PICOTCP_UDP=y\nCONFIG_PICOTCP_DNS=y\n# CONFIG_PICOTCP_MCAST is not set\n# CONFIG_PICOTCP_NAT is not set\n# CONFIG_PICOTCP_IPFILTER is not set\nCONFIG_PICOTCP_LOOP=y\n# CONFIG_PICOTCP_DEBUG is not set\n\n#\n# Device Drivers\n#\nDEVNULL=y\nDEVUART=y\n# USART_1 is not set\n# USART_2 is not set\n# USART_3 is not set\nUSART_6=y\nDEVSTM32USB=y\nDEVSTM32USBFS=y\n# USBFS_HOST is not set\nUSBFS_GUEST=y\n# DEVSTM32USBHS is not set\nDEV_USB_ETH=y\nUSB_DEFAULT_IP=\"192.168.6.150\"\nUSB_DEFAULT_NM=\"255.255.255.0\"\nUSB_DEFAULT_GW=\"192.168.6.1\"\n# DEVTIM is not set\n# DEVF7ETH is not set\nDEVSTM32SDIO=y\n# DEVSTM32I2C is not set\n# DEVSPI is not set\n# DEV_RANDOM is not set\nDEVFRAMEBUFFER=y\nDEVFBCON=y\nFONT_CGA_8X8=y\n# FONT_PICCOLO_7X6 is not set\nDEVF7DISCOLTDC=y\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/stm32f746-nucleo.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\n# ARCH_LPC17XX is not set\n# ARCH_STM32F4 is not set\nARCH_STM32F7=y\nARCH_STM32F746_NG=y\n# ARCH_STM32F769_NI is not set\nFLASH_SIZE_1MB=y\nRAM_SIZE_320KB=y\nARCH_STM32F746=y\nCLK_216MHZ=y\n# MACH_STM32F746Discovery is not set\nMACH_STM32F746Nucleo144=y\n# STM32F7_SDRAM is not set\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=128\nKRAMMEM_SIZE=32\n# TASK_STACK_SIZE_1K is not set\nTASK_STACK_SIZE_2K=y\n# TASK_STACK_SIZE_4K is not set\n# TASK_STACK_SIZE_8K is not set\nMPU=y\nPTHREADS=y\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\n# KLOG is not set\nMEMFAULT_DBG=y\n# HARDFAULT_DBG is not set\nSTRACE=y\n\n#\n# Filesystems\n#\nSYSFS=y\n# MEMFS is not set\nXIPFS=y\n# FATFS is not set\n\n#\n# Networking\n#\n# SOCK_INET is not set\n# TCPIP_MEMPOOL_YN is not set\n\n#\n# Device Drivers\n#\nDEVNULL=y\nDEVUART=y\n# USART_1 is not set\n# USART_2 is not set\n# USART_3 is not set\nUSART_6=y\nDEVSTM32USB=y\nDEVSTM32USBFS=y\nUSBFS_HOST=y\n# USBFS_GUEST is not set\n# DEVSTM32USBHS is not set\n# DEVTIM is not set\n# DEVSTM32SDIO is not set\n# DEVSTM32I2C is not set\n# DEVSPI is not set\n# DEV_RANDOM is not set\n# DEVFRAMEBUFFER is not set\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "defconfig/stm32f769-discovery.config",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Compiler options\n#\nGDB_CFLAG=y\nOPTIMIZE_NONE=y\n# OPTIMIZE_SIZE is not set\n# OPTIMIZE_PERF is not set\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\n# ARCH_LPC17XX is not set\n# ARCH_STM32F4 is not set\nARCH_STM32F7=y\n# ARCH_NRF51 is not set\n# ARCH_STM32F746_NG is not set\nARCH_STM32F769_NI=y\nFLASH_SIZE_2MB=y\nRAM_SIZE_368KB=y\nARCH_STM32F769=y\nCLK_216MHZ=y\nMACH_STM32F769Discovery=y\n# STM32F7_SDRAM is not set\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=128\nKRAMMEM_SIZE=64\n# TASK_STACK_SIZE_1K is not set\n# TASK_STACK_SIZE_2K is not set\nTASK_STACK_SIZE_4K=y\n# TASK_STACK_SIZE_8K is not set\nMPU=y\nPTHREADS=y\nSIGNALS=y\nPIPE=y\n# SOCK_UNIX is not set\n\n#\n# Debugging options\n#\nKLOG=y\nKLOG_SIZE=256\nMEMFAULT_DBG=y\nHARDFAULT_DBG=y\n# STRACE is not set\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\nFATFS=y\nFAT32=y\nFAT16=y\n\n#\n# Networking\n#\nSOCK_INET=y\n# TCPIP_MEMPOOL_YN is not set\nPICOTCP=y\n\n#\n# picoTCP configuration\n#\nCONFIG_PICOTCP_IPV4=y\n# CONFIG_PICOTCP_IPV6 is not set\nCONFIG_PICOTCP_TCP=y\nCONFIG_PICOTCP_UDP=y\nCONFIG_PICOTCP_DNS=y\n# CONFIG_PICOTCP_MCAST is not set\n# CONFIG_PICOTCP_NAT is not set\n# CONFIG_PICOTCP_IPFILTER is not set\nCONFIG_PICOTCP_LOOP=y\n# CONFIG_PICOTCP_DEBUG is not set\n\n#\n# Device Drivers\n#\nDEVNULL=y\nDEVUART=y\n# USART_1 is not set\n# USART_2 is not set\n# USART_3 is not set\nUSART_6=y\n# DEVSTM32USBHS is not set\nDEVF7ETH=y\nETH_DEFAULT_IP=\"192.168.2.151\"\nETH_DEFAULT_NM=\"255.255.255.0\"\nETH_DEFAULT_GW=\"192.168.2.1\"\nDEVSTM32SDIO=y\n# DEVSPI is not set\n# DEV_RANDOM is not set\n# DEVFRAMEBUFFER is not set\n\n#\n# Power Management\n#\n\n#\n# Power Management requires CPU Timer support\n#\n"
  },
  {
    "path": "gdbinit.bflt",
    "content": " tar ext :3333\n monitor reset\n layout src\n symbol-file\n file kernel.elf\n add-symbol-file ./frosted-mini-userspace-bflt/init.gdb 0x20090 -s .data 0x20008014 -s .bss 0x2000813c\n add-symbol-file frosted-mini-userspace-bflt/idling.gdb 0x20a84 -s .data 0x2000815c -s .bss 0x200081ac\n add-symbol-file frosted-mini-userspace-bflt/fresh.gdb 0x21334 -s .data 0x200081f8 -s .bss 0x20008b84\n add-symbol-file frosted-mini-userspace-bflt/binutils.gdb 0x18de0 -s .data 0x2000acf0 -s .bss 0x2000c610\n mon reset\n mon halt\n stepi\n focus c\n"
  },
  {
    "path": "gdbinit.mini",
    "content": " tar ext :3333\n monitor reset\n layout src\n symbol-file\n file kernel.elf\n mon reset\n mon halt\n stepi\n focus c\n"
  },
  {
    "path": "include/frosted_api.h",
    "content": "#ifndef INC_FROSTED_API\n#define INC_FROSTED_API\n#include \"stdint.h\"\n\n#define INIT __attribute__((section(\".init\")))\n\n/* Constants */\n\n/* move to limits.h ? */\n#define MAXPATHLEN 256\n#define ARG_MAX    32\n\n\n/* open */\n#include <sys/_default_fcntl.h>\n\n\n/* seek */\n#define SEEK_SET 0\n#define SEEK_CUR 1\n#define SEEK_END 2\n\n/* syslog */\n#define LOG_EMERG   0   /* system is unusable */\n#define LOG_ALERT   1   /* action must be taken immediately */\n#define LOG_CRIT    2   /* critical conditions */\n#define LOG_ERR     3   /* error conditions */\n#define LOG_WARNING 4   /* warning conditions */\n#define LOG_NOTICE  5   /* normal but significant condition */\n#define LOG_INFO    6   /* informational */\n#define LOG_DEBUG   7   /* debug-level messages */\n\n\n/* opendir - readdir */\ntypedef void DIR;\n\n/* semaphore */\nstruct semaphore;\ntypedef struct semaphore sem_t;\ntypedef struct semaphore mutex_t;\n\n#define MAX_FILE 64\nstruct dirent {\n    uint32_t d_ino;\n    char d_name[MAX_FILE];\n};\n\n/*\n#define S_IFMT     0170000   // bit mask for the file type bit fields\n#define P_IFMT     0000007   // bit mask for file permissions\n*/\n\n#define P_EXEC     0000001   // exec\n\n\n/* for unix sockets */\n#ifndef __frosted__\n#define AF_UNIX 0\n#define SOCK_STREAM 6\n#define SOCK_DGRAM 17\n#endif\n\nstruct __attribute__((packed)) sockaddr {\n    uint16_t sa_family;\n    uint8_t  sa_zero[14];\n};\n\nstruct __attribute__((packed)) sockaddr_un {\n    uint16_t sun_family;\n    uint8_t  sun_path[MAX_FILE - 2];\n};\n\nstruct sockaddr_env {\n    struct sockaddr *se_addr;\n    unsigned int se_len;\n};\n\nextern int errno;\n\n#endif\n"
  },
  {
    "path": "kconfig/.gitignore",
    "content": "#\n# Generated files\n#\nconfig*\n*.lex.c\n*.tab.c\n*.tab.h\nzconf.hash.c\n*.moc\ngconf.glade.h\n*.pot\n*.mo\n\n#\n# configuration programs\n#\nconf\nmconf\nnconf\nqconf\ngconf\nkxgettext\n"
  },
  {
    "path": "kconfig/Kconfig",
    "content": "mainmenu \"FROSTED Kernel Configuration\"\nsource ../kernel/Kconfig\n\n\n"
  },
  {
    "path": "kconfig/Makefile",
    "content": "# ===========================================================================\n# Kernel configuration targets\n# These targets are used from top-level makefile\n\nPHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \\\n\tlocalmodconfig localyesconfig\n\nifdef KBUILD_KCONFIG\nKconfig := $(KBUILD_KCONFIG)\nelse\nKconfig := Kconfig\nendif\n\n# We need this, in case the user has it in its environment\nunexport CONFIG_\n\nxconfig: $(obj)/qconf\n\t$< $(Kconfig)\n\ngconfig: $(obj)/gconf\n\t$< $(Kconfig)\n\nmenuconfig: $(obj)/mconf\n\techo obj is $(obj)\n\techo Executing $<\n\t$< $(Kconfig)\n\nconfig: $(obj)/conf\n\t$< --oldaskconfig $(Kconfig)\n\nnconfig: $(obj)/nconf\n\t$< $(Kconfig)\n\noldconfig: $(obj)/conf\n\t$< --$@ $(Kconfig)\n\nsilentoldconfig: $(obj)/conf\n\t$(Q)mkdir -p include/generated\n\t$< --$@ $(Kconfig)\n\nlocalyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf\n\t$(Q)mkdir -p include/generated\n\t$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config\n\t$(Q)if [ -f .config ]; then \t\t\t\t\t\\\n\t\t\tcmp -s .tmp.config .config ||\t\t\t\\\n\t\t\t(mv -f .config .config.old.1;\t\t\t\\\n\t\t\t mv -f .tmp.config .config;\t\t\t\\\n\t\t\t $(obj)/conf --silentoldconfig $(Kconfig);\t\\\n\t\t\t mv -f .config.old.1 .config.old)\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t\tmv -f .tmp.config .config;\t\t\t\\\n\t\t\t$(obj)/conf --silentoldconfig $(Kconfig);\t\\\n\tfi\n\t$(Q)rm -f .tmp.config\n\n# Create new linux.pot file\n# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files\nupdate-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h\n\t$(Q)echo \"  GEN     config.pot\"\n\t$(Q)xgettext --default-domain=linux                         \\\n\t    --add-comments --keyword=_ --keyword=N_                 \\\n\t    --from-code=UTF-8                                       \\\n\t    --files-from=$(srctree)/scripts/kconfig/POTFILES.in     \\\n\t    --directory=$(srctree) --directory=$(objtree)           \\\n\t    --output $(obj)/config.pot\n\t$(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot\n\t$(Q)(for i in `ls $(srctree)/arch/*/Kconfig      \\\n\t    $(srctree)/arch/*/um/Kconfig`;               \\\n\t    do                                           \\\n\t\techo \"  GEN     $$i\";                    \\\n\t\t$(obj)/kxgettext $$i                     \\\n\t\t     >> $(obj)/config.pot;               \\\n\t    done )\n\t$(Q)echo \"  GEN     linux.pot\"\n\t$(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \\\n\t    --output $(obj)/linux.pot\n\t$(Q)rm -f $(obj)/config.pot\n\nPHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig\n\nallnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf\n\t$< --$@ $(Kconfig)\n\nPHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig\n\nlistnewconfig olddefconfig: $(obj)/conf\n\t$< --$@ $(Kconfig)\n\n# oldnoconfig is an alias of olddefconfig, because people already are dependent\n# on its behavior(sets new symbols to their default value but not 'n') with the\n# counter-intuitive name.\noldnoconfig: $(obj)/conf\n\t$< --olddefconfig $(Kconfig)\n\nsavedefconfig: $(obj)/conf\n\t$< --$@=defconfig $(Kconfig)\n\ndefconfig: $(obj)/conf\nifeq ($(KBUILD_DEFCONFIG),)\n\t$< --defconfig $(Kconfig)\nelse\n\t@echo \"*** Default configuration is based on '$(KBUILD_DEFCONFIG)'\"\n\t$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)\nendif\n\n%_defconfig: $(obj)/conf\n\t$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)\n\n# Help text used by make help\nhelp:\n\t@echo  '  config\t  - Update current config utilising a line-oriented program'\n\t@echo  '  nconfig         - Update current config utilising a ncurses menu based program'\n\t@echo  '  menuconfig\t  - Update current config utilising a menu based program'\n\t@echo  '  xconfig\t  - Update current config utilising a QT based front-end'\n\t@echo  '  gconfig\t  - Update current config utilising a GTK based front-end'\n\t@echo  '  oldconfig\t  - Update current config utilising a provided .config as base'\n\t@echo  '  localmodconfig  - Update current config disabling modules not loaded'\n\t@echo  '  localyesconfig  - Update current config converting local mods to core'\n\t@echo  '  silentoldconfig - Same as oldconfig, but quietly, additionally update deps'\n\t@echo  '  defconfig\t  - New config with default from ARCH supplied defconfig'\n\t@echo  '  savedefconfig   - Save current config as ./defconfig (minimal config)'\n\t@echo  '  allnoconfig\t  - New config where all options are answered with no'\n\t@echo  '  allyesconfig\t  - New config where all options are accepted with yes'\n\t@echo  '  allmodconfig\t  - New config selecting modules when possible'\n\t@echo  '  alldefconfig    - New config with all symbols set to default'\n\t@echo  '  randconfig\t  - New config with random answer to all options'\n\t@echo  '  listnewconfig   - List new options'\n\t@echo  '  olddefconfig\t  - Same as silentoldconfig but sets new symbols to their default value'\n\n# lxdialog stuff\ncheck-lxdialog  := $(srctree)/$(src)/lxdialog/check-lxdialog.sh\n\n# Use recursively expanded variables so we do not call gcc unless\n# we really need to do so. (Do not call gcc as part of make mrproper)\nHOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \\\n                    -DLOCALE\n\n# ===========================================================================\n# Shared Makefile for the various kconfig executables:\n# conf:\t  Used for defconfig, oldconfig and related targets\n# nconf:  Used for the nconfig target.\n#         Utilizes ncurses\n# mconf:  Used for the menuconfig target\n#         Utilizes the lxdialog package\n# qconf:  Used for the xconfig target\n#         Based on QT which needs to be installed to compile it\n# gconf:  Used for the gconfig target\n#         Based on GTK which needs to be installed to compile it\n# object files used by all kconfig flavours\n\nlxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o\nlxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o\n\nconf-objs\t:= conf.o  zconf.tab.o\nmconf-objs     := mconf.o zconf.tab.o $(lxdialog)\nnconf-objs     := nconf.o zconf.tab.o nconf.gui.o\nkxgettext-objs\t:= kxgettext.o zconf.tab.o\nqconf-cxxobjs\t:= qconf.o\nqconf-objs\t:= zconf.tab.o\ngconf-objs\t:= gconf.o zconf.tab.o\n\nhostprogs-y := conf\n\nifeq ($(MAKECMDGOALS),nconfig)\n\thostprogs-y += nconf\nendif\n\nifeq ($(MAKECMDGOALS),menuconfig)\n\thostprogs-y += mconf\nendif\n\nifeq ($(MAKECMDGOALS),update-po-config)\n\thostprogs-y += kxgettext\nendif\n\nifeq ($(MAKECMDGOALS),xconfig)\n\tqconf-target := 1\nendif\nifeq ($(MAKECMDGOALS),gconfig)\n\tgconf-target := 1\nendif\n\n\nifeq ($(qconf-target),1)\n\thostprogs-y += qconf\nendif\n\nifeq ($(gconf-target),1)\n\thostprogs-y += gconf\nendif\n\nclean-files\t:= qconf.moc .tmp_qtcheck .tmp_gtkcheck\nclean-files\t+= zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h\nclean-files     += mconf qconf gconf nconf\nclean-files     += config.pot linux.pot\n\n# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)\nPHONY += $(obj)/dochecklxdialog\n$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog\n$(obj)/dochecklxdialog:\n\t$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)\n\nalways := dochecklxdialog\n\n# Add environment specific flags\nHOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))\n\n# generated files seem to need this to find local include files\nHOSTCFLAGS_zconf.lex.o\t:= -I$(src)\nHOSTCFLAGS_zconf.tab.o\t:= -I$(src)\n\nLEX_PREFIX_zconf\t:= zconf\nYACC_PREFIX_zconf\t:= zconf\n\nHOSTLOADLIBES_qconf\t= $(KC_QT_LIBS)\nHOSTCXXFLAGS_qconf.o\t= $(KC_QT_CFLAGS)\n\nHOSTLOADLIBES_gconf\t= `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`\nHOSTCFLAGS_gconf.o\t= `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \\\n                          -Wno-missing-prototypes\n\nHOSTLOADLIBES_mconf   = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))\n\nHOSTLOADLIBES_nconf\t= $(shell \\\n\t\t\t\tpkg-config --libs menu panel ncurses 2>/dev/null \\\n\t\t\t\t|| echo \"-lmenu -lpanel -lncurses\"  )\n$(obj)/qconf.o: $(obj)/.tmp_qtcheck\n\nifeq ($(qconf-target),1)\n$(obj)/.tmp_qtcheck: $(src)/Makefile\n-include $(obj)/.tmp_qtcheck\n\n# QT needs some extra effort...\n$(obj)/.tmp_qtcheck:\n\t@set -e; echo \"  CHECK   qt\"; dir=\"\"; pkg=\"\"; \\\n\tif ! pkg-config --exists QtCore 2> /dev/null; then \\\n\t    echo \"* Unable to find the QT4 tool qmake. Trying to use QT3\"; \\\n\t    pkg-config --exists qt 2> /dev/null && pkg=qt; \\\n\t    pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \\\n\t    if [ -n \"$$pkg\" ]; then \\\n\t      cflags=\"\\$$(shell pkg-config $$pkg --cflags)\"; \\\n\t      libs=\"\\$$(shell pkg-config $$pkg --libs)\"; \\\n\t      moc=\"\\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc\"; \\\n\t      dir=\"$$(pkg-config $$pkg --variable=prefix)\"; \\\n\t    else \\\n\t      for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \\\n\t        if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \\\n\t      done; \\\n\t      if [ -z \"$$dir\" ]; then \\\n\t        echo >&2 \"*\"; \\\n\t        echo >&2 \"* Unable to find any QT installation. Please make sure that\"; \\\n\t        echo >&2 \"* the QT4 or QT3 development package is correctly installed and\"; \\\n\t        echo >&2 \"* either qmake can be found or install pkg-config or set\"; \\\n\t        echo >&2 \"* the QTDIR environment variable to the correct location.\"; \\\n\t        echo >&2 \"*\"; \\\n\t        false; \\\n\t      fi; \\\n\t      libpath=$$dir/lib; lib=qt; osdir=\"\"; \\\n\t      $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \\\n\t        osdir=x$$($(HOSTCXX) -print-multi-os-directory); \\\n\t      test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \\\n\t      test -f $$libpath/libqt-mt.so && lib=qt-mt; \\\n\t      cflags=\"-I$$dir/include\"; \\\n\t      libs=\"-L$$libpath -Wl,-rpath,$$libpath -l$$lib\"; \\\n\t      moc=\"$$dir/bin/moc\"; \\\n\t    fi; \\\n\t    if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \\\n\t      echo \"*\"; \\\n\t      echo \"* Unable to find $$dir/bin/moc, using /usr/bin/moc instead.\"; \\\n\t      echo \"*\"; \\\n\t      moc=\"/usr/bin/moc\"; \\\n\t    fi; \\\n\telse \\\n\t  cflags=\"\\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)\"; \\\n\t  libs=\"\\$$(shell pkg-config QtCore QtGui Qt3Support --libs)\"; \\\n\t  moc=\"\\$$(shell pkg-config QtCore --variable=moc_location)\"; \\\n\t  [ -n \"$$moc\" ] || moc=\"\\$$(shell pkg-config QtCore --variable=prefix)/bin/moc\"; \\\n\tfi; \\\n\techo \"KC_QT_CFLAGS=$$cflags\" > $@; \\\n\techo \"KC_QT_LIBS=$$libs\" >> $@; \\\n\techo \"KC_QT_MOC=$$moc\" >> $@\nendif\n\n$(obj)/gconf.o: $(obj)/.tmp_gtkcheck\n\nifeq ($(gconf-target),1)\n-include $(obj)/.tmp_gtkcheck\n\n# GTK needs some extra effort, too...\n$(obj)/.tmp_gtkcheck:\n\t@if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then\t\t\\\n\t\tif `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then\t\t\t\\\n\t\t\ttouch $@;\t\t\t\t\t\t\t\t\\\n\t\telse\t\t\t\t\t\t\t\t\t\\\n\t\t\techo >&2 \"*\"; \t\t\t\t\t\t\t\\\n\t\t\techo >&2 \"* GTK+ is present but version >= 2.0.0 is required.\";\t\\\n\t\t\techo >&2 \"*\";\t\t\t\t\t\t\t\\\n\t\t\tfalse;\t\t\t\t\t\t\t\t\\\n\t\tfi\t\t\t\t\t\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\t\t\\\n\t\techo >&2 \"*\"; \t\t\t\t\t\t\t\t\\\n\t\techo >&2 \"* Unable to find the GTK+ installation. Please make sure that\"; \t\\\n\t\techo >&2 \"* the GTK+ 2.0 development package is correctly installed...\"; \t\\\n\t\techo >&2 \"* You need gtk+-2.0, glib-2.0 and libglade-2.0.\"; \t\t\\\n\t\techo >&2 \"*\"; \t\t\t\t\t\t\t\t\\\n\t\tfalse;\t\t\t\t\t\t\t\t\t\\\n\tfi\nendif\n\n$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c\n\n$(obj)/qconf.o: $(obj)/qconf.moc\n\nquiet_cmd_moc = MOC     $@\n      cmd_moc = $(KC_QT_MOC) -i $< -o $@\n\n$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck\n\t$(call cmd,moc)\n\n# Extract gconf menu items for I18N support\n$(obj)/gconf.glade.h: $(obj)/gconf.glade\n\t$(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \\\n\t$(obj)/gconf.glade\n\n"
  },
  {
    "path": "kconfig/Makefile.frosted",
    "content": "src := .\ntop_srcdir=../../\ntop_builddir=../../\nsrctree := .\nobj ?= .\n\ninclude Makefile\n#HOSTCFLAGS+=-Dinline=\"\" -include foo.h\n\n#CFLAGS+=-DCURSES_LOC=\"<ncurses.h>\"\n#CFLAGS+=-DLOCALE\nHOSTCC?=gcc\nPATH:=$(PATH):.\n\n-include $(obj)/.depend\n$(obj)/.depend: $(wildcard *.h *.c)\n\t$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) -MM *.c > $@ 2>/dev/null || :\n\n__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))\nhost-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))\nhost-cmulti := $(foreach m,$(__hostprogs),\\\n           $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))\nhost-cxxmulti := $(foreach m,$(__hostprogs),\\\n           $(if $($(m)-cxxobjs),$(m),$(if $($(m)-objs),)))\nhost-cobjs := $(addprefix $(obj)/,$(sort $(foreach m,$(__hostprogs),$($(m)-objs))))\nhost-cxxobjs := $(addprefix $(obj)/,$(sort $(foreach m,$(__hostprogs),$($(m)-cxxobjs))))\n\nHOST_EXTRACFLAGS += -I$(obj) -DCONFIG_=\\\"\\\"\n\n$(host-csingle): %: %.c\n\t$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) $< -o $(obj)/$@\n\n$(host-cmulti): %: $(host-cobjs) $(host-cshlib)\n\t$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) $(addprefix $(obj)/,$($(@F)-objs)) $(HOSTLOADLIBES_$(@F)) -o $(obj)/$@\n\n$(host-cxxmulti): %: $(host-cxxobjs) $(host-cobjs) $(host-cshlib)\n\t$(HOSTCXX) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCXXFLAGS_$@) $(addprefix $(obj)/,$($(@F)-objs) $($(@F)-cxxobjs)) $(HOSTLOADLIBES_$(@F)) -o $(obj)/$@\n\n$(obj)/%.o: %.c\n\t$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$(@F)) -c $< -o $@\n\n$(obj)/%.o: $(obj)/%.c\n\t$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$(@F)) -c $< -o $@\n\n$(obj)/%.o: %.cc\n\t$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCXXFLAGS_$(@F)) -c $< -o $@\n\n$(obj)/%:: $(src)/%_shipped\n\t$(Q)cat $< > $@\n\nclean:\n\t$(Q)rm -f $(addprefix $(obj)/,$(clean-files))\ndistclean: clean\n\t$(Q)rm -f $(addprefix $(obj)/,$(lxdialog) $(conf-objs) $(mconf-objs) $(kxgettext-objs) \\\n\t\t$(hostprogs-y) $(qconf-cxxobjs) $(qconf-objs) $(gconf-objs) \\\n\t\tmconf .depend)\n\nFORCE:\n.PHONY: FORCE clean distclean \n"
  },
  {
    "path": "kconfig/POTFILES.in",
    "content": "scripts/kconfig/lxdialog/checklist.c\nscripts/kconfig/lxdialog/inputbox.c\nscripts/kconfig/lxdialog/menubox.c\nscripts/kconfig/lxdialog/textbox.c\nscripts/kconfig/lxdialog/util.c\nscripts/kconfig/lxdialog/yesno.c\nscripts/kconfig/mconf.c\nscripts/kconfig/conf.c\nscripts/kconfig/confdata.c\nscripts/kconfig/gconf.c\nscripts/kconfig/gconf.glade.h\nscripts/kconfig/qconf.cc\n"
  },
  {
    "path": "kconfig/STM32F4x1Discovery.cfg",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\n# ARCH_LPC17XX is not set\nARCH_STM32F4=y\n# ARCH_STM32F401_XB is not set\n# ARCH_STM32F401_XC is not set\n# ARCH_STM32F401_XD is not set\n# ARCH_STM32F401_XE is not set\n# ARCH_STM32F405_XG is not set\n# ARCH_STM32F405_XE is not set\n# ARCH_STM32F407_XG is not set\n# ARCH_STM32F407_XE is not set\nARCH_STM32F411_XE=y\n# ARCH_STM32F411_XC is not set\n# ARCH_STM32F429_XE is not set\n# ARCH_STM32F429_XG is not set\n# ARCH_STM32F429_XI is not set\nFLASH_SIZE_512KB=y\nRAM_SIZE_128KB=y\nARCH_STM32F411=y\nCLK_48MHZ=y\n# CLK_84MHZ is not set\nMACH_STM32F4x1Discovery=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=48\nKRAMMEM_SIZE=16\n\n#\n# Subsystems\n#\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\n\n#\n# Sockets\n#\nSOCK_UNIX=y\n\n#\n# Devices\n#\nDEVNULL=y\nDEVUART=y\n# USART_1 is not set\nUSART_2=y\n# USART_6 is not set\nDEVSPI=y\nSPI_1=y\nDEVL3GD20=y\nDEVGPIO=y\n\n#\n# Applications\n#\nFRESH=y\n# TASK2 is not set\n# PRODCONS is not set\n"
  },
  {
    "path": "kconfig/check.sh",
    "content": "#!/bin/sh\n# Needed for systems without gettext\n$* -x c -o /dev/null - > /dev/null 2>&1 << EOF\n#include <libintl.h>\nint main()\n{\n\tgettext(\"\");\n\treturn 0;\n}\nEOF\nif [ ! \"$?\" -eq \"0\"  ]; then\n\techo -DKBUILD_NO_NLS;\nfi\n\n"
  },
  {
    "path": "kconfig/conf.c",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <locale.h>\n#include <ctype.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n#include <getopt.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <errno.h>\n\n#include \"lkc.h\"\n\nstatic void conf(struct menu *menu);\nstatic void check_conf(struct menu *menu);\nstatic void xfgets(char *str, int size, FILE *in);\n\nenum input_mode {\n\toldaskconfig,\n\tsilentoldconfig,\n\toldconfig,\n\tallnoconfig,\n\tallyesconfig,\n\tallmodconfig,\n\talldefconfig,\n\trandconfig,\n\tdefconfig,\n\tsavedefconfig,\n\tlistnewconfig,\n\tolddefconfig,\n} input_mode = oldaskconfig;\n\nstatic int indent = 1;\nstatic int tty_stdio;\nstatic int valid_stdin = 1;\nstatic int sync_kconfig;\nstatic int conf_cnt;\nstatic char line[128];\nstatic struct menu *rootEntry;\n\nstatic void print_help(struct menu *menu)\n{\n\tstruct gstr help = str_new();\n\n\tmenu_get_ext_help(menu, &help);\n\n\tprintf(\"\\n%s\\n\", str_get(&help));\n\tstr_free(&help);\n}\n\nstatic void strip(char *str)\n{\n\tchar *p = str;\n\tint l;\n\n\twhile ((isspace(*p)))\n\t\tp++;\n\tl = strlen(p);\n\tif (p != str)\n\t\tmemmove(str, p, l + 1);\n\tif (!l)\n\t\treturn;\n\tp = str + l - 1;\n\twhile ((isspace(*p)))\n\t\t*p-- = 0;\n}\n\nstatic void check_stdin(void)\n{\n\tif (!valid_stdin) {\n\t\tprintf(_(\"aborted!\\n\\n\"));\n\t\tprintf(_(\"Console input/output is redirected. \"));\n\t\tprintf(_(\"Run 'make oldconfig' to update configuration.\\n\\n\"));\n\t\texit(1);\n\t}\n}\n\nstatic int conf_askvalue(struct symbol *sym, const char *def)\n{\n\tenum symbol_type type = sym_get_type(sym);\n\n\tif (!sym_has_value(sym))\n\t\tprintf(_(\"(NEW) \"));\n\n\tline[0] = '\\n';\n\tline[1] = 0;\n\n\tif (!sym_is_changable(sym)) {\n\t\tprintf(\"%s\\n\", def);\n\t\tline[0] = '\\n';\n\t\tline[1] = 0;\n\t\treturn 0;\n\t}\n\n\tswitch (input_mode) {\n\tcase oldconfig:\n\tcase silentoldconfig:\n\t\tif (sym_has_value(sym)) {\n\t\t\tprintf(\"%s\\n\", def);\n\t\t\treturn 0;\n\t\t}\n\t\tcheck_stdin();\n\t\t/* fall through */\n\tcase oldaskconfig:\n\t\tfflush(stdout);\n\t\txfgets(line, 128, stdin);\n\t\tif (!tty_stdio)\n\t\t\tprintf(\"\\n\");\n\t\treturn 1;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tswitch (type) {\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tprintf(\"%s\\n\", def);\n\t\treturn 1;\n\tdefault:\n\t\t;\n\t}\n\tprintf(\"%s\", line);\n\treturn 1;\n}\n\nstatic int conf_string(struct menu *menu)\n{\n\tstruct symbol *sym = menu->sym;\n\tconst char *def;\n\n\twhile (1) {\n\t\tprintf(\"%*s%s \", indent - 1, \"\", _(menu->prompt->text));\n\t\tprintf(\"(%s) \", sym->name);\n\t\tdef = sym_get_string_value(sym);\n\t\tif (sym_get_string_value(sym))\n\t\t\tprintf(\"[%s] \", def);\n\t\tif (!conf_askvalue(sym, def))\n\t\t\treturn 0;\n\t\tswitch (line[0]) {\n\t\tcase '\\n':\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\t/* print help */\n\t\t\tif (line[1] == '\\n') {\n\t\t\t\tprint_help(menu);\n\t\t\t\tdef = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* fall through */\n\t\tdefault:\n\t\t\tline[strlen(line)-1] = 0;\n\t\t\tdef = line;\n\t\t}\n\t\tif (def && sym_set_string_value(sym, def))\n\t\t\treturn 0;\n\t}\n}\n\nstatic int conf_sym(struct menu *menu)\n{\n\tstruct symbol *sym = menu->sym;\n\ttristate oldval, newval;\n\n\twhile (1) {\n\t\tprintf(\"%*s%s \", indent - 1, \"\", _(menu->prompt->text));\n\t\tif (sym->name)\n\t\t\tprintf(\"(%s) \", sym->name);\n\t\tputchar('[');\n\t\toldval = sym_get_tristate_value(sym);\n\t\tswitch (oldval) {\n\t\tcase no:\n\t\t\tputchar('N');\n\t\t\tbreak;\n\t\tcase mod:\n\t\t\tputchar('M');\n\t\t\tbreak;\n\t\tcase yes:\n\t\t\tputchar('Y');\n\t\t\tbreak;\n\t\t}\n\t\tif (oldval != no && sym_tristate_within_range(sym, no))\n\t\t\tprintf(\"/n\");\n\t\tif (oldval != mod && sym_tristate_within_range(sym, mod))\n\t\t\tprintf(\"/m\");\n\t\tif (oldval != yes && sym_tristate_within_range(sym, yes))\n\t\t\tprintf(\"/y\");\n\t\tif (menu_has_help(menu))\n\t\t\tprintf(\"/?\");\n\t\tprintf(\"] \");\n\t\tif (!conf_askvalue(sym, sym_get_string_value(sym)))\n\t\t\treturn 0;\n\t\tstrip(line);\n\n\t\tswitch (line[0]) {\n\t\tcase 'n':\n\t\tcase 'N':\n\t\t\tnewval = no;\n\t\t\tif (!line[1] || !strcmp(&line[1], \"o\"))\n\t\t\t\tbreak;\n\t\t\tcontinue;\n\t\tcase 'm':\n\t\tcase 'M':\n\t\t\tnewval = mod;\n\t\t\tif (!line[1])\n\t\t\t\tbreak;\n\t\t\tcontinue;\n\t\tcase 'y':\n\t\tcase 'Y':\n\t\t\tnewval = yes;\n\t\t\tif (!line[1] || !strcmp(&line[1], \"es\"))\n\t\t\t\tbreak;\n\t\t\tcontinue;\n\t\tcase 0:\n\t\t\tnewval = oldval;\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\tgoto help;\n\t\tdefault:\n\t\t\tcontinue;\n\t\t}\n\t\tif (sym_set_tristate_value(sym, newval))\n\t\t\treturn 0;\nhelp:\n\t\tprint_help(menu);\n\t}\n}\n\nstatic int conf_choice(struct menu *menu)\n{\n\tstruct symbol *sym, *def_sym;\n\tstruct menu *child;\n\tbool is_new;\n\n\tsym = menu->sym;\n\tis_new = !sym_has_value(sym);\n\tif (sym_is_changable(sym)) {\n\t\tconf_sym(menu);\n\t\tsym_calc_value(sym);\n\t\tswitch (sym_get_tristate_value(sym)) {\n\t\tcase no:\n\t\t\treturn 1;\n\t\tcase mod:\n\t\t\treturn 0;\n\t\tcase yes:\n\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tswitch (sym_get_tristate_value(sym)) {\n\t\tcase no:\n\t\t\treturn 1;\n\t\tcase mod:\n\t\t\tprintf(\"%*s%s\\n\", indent - 1, \"\", _(menu_get_prompt(menu)));\n\t\t\treturn 0;\n\t\tcase yes:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\twhile (1) {\n\t\tint cnt, def;\n\n\t\tprintf(\"%*s%s\\n\", indent - 1, \"\", _(menu_get_prompt(menu)));\n\t\tdef_sym = sym_get_choice_value(sym);\n\t\tcnt = def = 0;\n\t\tline[0] = 0;\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (!menu_is_visible(child))\n\t\t\t\tcontinue;\n\t\t\tif (!child->sym) {\n\t\t\t\tprintf(\"%*c %s\\n\", indent, '*', _(menu_get_prompt(child)));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcnt++;\n\t\t\tif (child->sym == def_sym) {\n\t\t\t\tdef = cnt;\n\t\t\t\tprintf(\"%*c\", indent, '>');\n\t\t\t} else\n\t\t\t\tprintf(\"%*c\", indent, ' ');\n\t\t\tprintf(\" %d. %s\", cnt, _(menu_get_prompt(child)));\n\t\t\tif (child->sym->name)\n\t\t\t\tprintf(\" (%s)\", child->sym->name);\n\t\t\tif (!sym_has_value(child->sym))\n\t\t\t\tprintf(_(\" (NEW)\"));\n\t\t\tprintf(\"\\n\");\n\t\t}\n\t\tprintf(_(\"%*schoice\"), indent - 1, \"\");\n\t\tif (cnt == 1) {\n\t\t\tprintf(\"[1]: 1\\n\");\n\t\t\tgoto conf_childs;\n\t\t}\n\t\tprintf(\"[1-%d\", cnt);\n\t\tif (menu_has_help(menu))\n\t\t\tprintf(\"?\");\n\t\tprintf(\"]: \");\n\t\tswitch (input_mode) {\n\t\tcase oldconfig:\n\t\tcase silentoldconfig:\n\t\t\tif (!is_new) {\n\t\t\t\tcnt = def;\n\t\t\t\tprintf(\"%d\\n\", cnt);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcheck_stdin();\n\t\t\t/* fall through */\n\t\tcase oldaskconfig:\n\t\t\tfflush(stdout);\n\t\t\txfgets(line, 128, stdin);\n\t\t\tstrip(line);\n\t\t\tif (line[0] == '?') {\n\t\t\t\tprint_help(menu);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!line[0])\n\t\t\t\tcnt = def;\n\t\t\telse if (isdigit(line[0]))\n\t\t\t\tcnt = atoi(line);\n\t\t\telse\n\t\t\t\tcontinue;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\tconf_childs:\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (!child->sym || !menu_is_visible(child))\n\t\t\t\tcontinue;\n\t\t\tif (!--cnt)\n\t\t\t\tbreak;\n\t\t}\n\t\tif (!child)\n\t\t\tcontinue;\n\t\tif (line[0] && line[strlen(line) - 1] == '?') {\n\t\t\tprint_help(child);\n\t\t\tcontinue;\n\t\t}\n\t\tsym_set_choice_value(sym, child->sym);\n\t\tfor (child = child->list; child; child = child->next) {\n\t\t\tindent += 2;\n\t\t\tconf(child);\n\t\t\tindent -= 2;\n\t\t}\n\t\treturn 1;\n\t}\n}\n\nstatic void conf(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct menu *child;\n\n\tif (!menu_is_visible(menu))\n\t\treturn;\n\n\tsym = menu->sym;\n\tprop = menu->prompt;\n\tif (prop) {\n\t\tconst char *prompt;\n\n\t\tswitch (prop->type) {\n\t\tcase P_MENU:\n\t\t\tif ((input_mode == silentoldconfig ||\n\t\t\t     input_mode == listnewconfig ||\n\t\t\t     input_mode == olddefconfig) &&\n\t\t\t    rootEntry != menu) {\n\t\t\t\tcheck_conf(menu);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t/* fall through */\n\t\tcase P_COMMENT:\n\t\t\tprompt = menu_get_prompt(menu);\n\t\t\tif (prompt)\n\t\t\t\tprintf(\"%*c\\n%*c %s\\n%*c\\n\",\n\t\t\t\t\tindent, '*',\n\t\t\t\t\tindent, '*', _(prompt),\n\t\t\t\t\tindent, '*');\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t}\n\n\tif (!sym)\n\t\tgoto conf_childs;\n\n\tif (sym_is_choice(sym)) {\n\t\tconf_choice(menu);\n\t\tif (sym->curr.tri != mod)\n\t\t\treturn;\n\t\tgoto conf_childs;\n\t}\n\n\tswitch (sym->type) {\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tconf_string(menu);\n\t\tbreak;\n\tdefault:\n\t\tconf_sym(menu);\n\t\tbreak;\n\t}\n\nconf_childs:\n\tif (sym)\n\t\tindent += 2;\n\tfor (child = menu->list; child; child = child->next)\n\t\tconf(child);\n\tif (sym)\n\t\tindent -= 2;\n}\n\nstatic void check_conf(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct menu *child;\n\n\tif (!menu_is_visible(menu))\n\t\treturn;\n\n\tsym = menu->sym;\n\tif (sym && !sym_has_value(sym)) {\n\t\tif (sym_is_changable(sym) ||\n\t\t    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {\n\t\t\tif (input_mode == listnewconfig) {\n\t\t\t\tif (sym->name && !sym_is_choice_value(sym)) {\n\t\t\t\t\tprintf(\"%s%s\\n\", CONFIG_, sym->name);\n\t\t\t\t}\n\t\t\t} else if (input_mode != olddefconfig) {\n\t\t\t\tif (!conf_cnt++)\n\t\t\t\t\tprintf(_(\"*\\n* Restart config...\\n*\\n\"));\n\t\t\t\trootEntry = menu_get_parent_menu(menu);\n\t\t\t\tconf(rootEntry);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (child = menu->list; child; child = child->next)\n\t\tcheck_conf(child);\n}\n\nstatic struct option long_opts[] = {\n\t{\"oldaskconfig\",    no_argument,       NULL, oldaskconfig},\n\t{\"oldconfig\",       no_argument,       NULL, oldconfig},\n\t{\"silentoldconfig\", no_argument,       NULL, silentoldconfig},\n\t{\"defconfig\",       optional_argument, NULL, defconfig},\n\t{\"savedefconfig\",   required_argument, NULL, savedefconfig},\n\t{\"allnoconfig\",     no_argument,       NULL, allnoconfig},\n\t{\"allyesconfig\",    no_argument,       NULL, allyesconfig},\n\t{\"allmodconfig\",    no_argument,       NULL, allmodconfig},\n\t{\"alldefconfig\",    no_argument,       NULL, alldefconfig},\n\t{\"randconfig\",      no_argument,       NULL, randconfig},\n\t{\"listnewconfig\",   no_argument,       NULL, listnewconfig},\n\t{\"olddefconfig\",    no_argument,       NULL, olddefconfig},\n\t/*\n\t * oldnoconfig is an alias of olddefconfig, because people already\n\t * are dependent on its behavior(sets new symbols to their default\n\t * value but not 'n') with the counter-intuitive name.\n\t */\n\t{\"oldnoconfig\",     no_argument,       NULL, olddefconfig},\n\t{NULL, 0, NULL, 0}\n};\n\nstatic void conf_usage(const char *progname)\n{\n\n\tprintf(\"Usage: %s [option] <kconfig-file>\\n\", progname);\n\tprintf(\"[option] is _one_ of the following:\\n\");\n\tprintf(\"  --listnewconfig         List new options\\n\");\n\tprintf(\"  --oldaskconfig          Start a new configuration using a line-oriented program\\n\");\n\tprintf(\"  --oldconfig             Update a configuration using a provided .config as base\\n\");\n\tprintf(\"  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\\n\");\n\tprintf(\"  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\\n\");\n\tprintf(\"  --oldnoconfig           An alias of olddefconfig\\n\");\n\tprintf(\"  --defconfig <file>      New config with default defined in <file>\\n\");\n\tprintf(\"  --savedefconfig <file>  Save the minimal current configuration to <file>\\n\");\n\tprintf(\"  --allnoconfig           New config where all options are answered with no\\n\");\n\tprintf(\"  --allyesconfig          New config where all options are answered with yes\\n\");\n\tprintf(\"  --allmodconfig          New config where all options are answered with mod\\n\");\n\tprintf(\"  --alldefconfig          New config with all symbols set to default\\n\");\n\tprintf(\"  --randconfig            New config with random answer to all options\\n\");\n}\n\nint main(int ac, char **av)\n{\n\tconst char *progname = av[0];\n\tint opt;\n\tconst char *name, *defconfig_file = NULL /* gcc uninit */;\n\tstruct stat tmpstat;\n\n\tsetlocale(LC_ALL, \"\");\n\tbindtextdomain(PACKAGE, LOCALEDIR);\n\ttextdomain(PACKAGE);\n\n\ttty_stdio = isatty(0) && isatty(1) && isatty(2);\n\n\twhile ((opt = getopt_long(ac, av, \"\", long_opts, NULL)) != -1) {\n\t\tinput_mode = (enum input_mode)opt;\n\t\tswitch (opt) {\n\t\tcase silentoldconfig:\n\t\t\tsync_kconfig = 1;\n\t\t\tbreak;\n\t\tcase defconfig:\n\t\tcase savedefconfig:\n\t\t\tdefconfig_file = optarg;\n\t\t\tbreak;\n\t\tcase randconfig:\n\t\t{\n\t\t\tstruct timeval now;\n\t\t\tunsigned int seed;\n\t\t\tchar *seed_env;\n\n\t\t\t/*\n\t\t\t * Use microseconds derived seed,\n\t\t\t * compensate for systems where it may be zero\n\t\t\t */\n\t\t\tgettimeofday(&now, NULL);\n\t\t\tseed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));\n\n\t\t\tseed_env = getenv(\"KCONFIG_SEED\");\n\t\t\tif( seed_env && *seed_env ) {\n\t\t\t\tchar *endp;\n\t\t\t\tint tmp = (int)strtol(seed_env, &endp, 0);\n\t\t\t\tif (*endp == '\\0') {\n\t\t\t\t\tseed = tmp;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfprintf( stderr, \"KCONFIG_SEED=0x%X\\n\", seed );\n\t\t\tsrand(seed);\n\t\t\tbreak;\n\t\t}\n\t\tcase oldaskconfig:\n\t\tcase oldconfig:\n\t\tcase allnoconfig:\n\t\tcase allyesconfig:\n\t\tcase allmodconfig:\n\t\tcase alldefconfig:\n\t\tcase listnewconfig:\n\t\tcase olddefconfig:\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\tconf_usage(progname);\n\t\t\texit(1);\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (ac == optind) {\n\t\tprintf(_(\"%s: Kconfig file missing\\n\"), av[0]);\n\t\tconf_usage(progname);\n\t\texit(1);\n\t}\n\tname = av[optind];\n\tconf_parse(name);\n\t//zconfdump(stdout);\n\tif (sync_kconfig) {\n\t\tname = conf_get_configname();\n\t\tif (stat(name, &tmpstat)) {\n\t\t\tfprintf(stderr, _(\"***\\n\"\n\t\t\t\t\"*** Configuration file \\\"%s\\\" not found!\\n\"\n\t\t\t\t\"***\\n\"\n\t\t\t\t\"*** Please run some configurator (e.g. \\\"make oldconfig\\\" or\\n\"\n\t\t\t\t\"*** \\\"make menuconfig\\\" or \\\"make xconfig\\\").\\n\"\n\t\t\t\t\"***\\n\"), name);\n\t\t\texit(1);\n\t\t}\n\t}\n\n\tswitch (input_mode) {\n\tcase defconfig:\n\t\tif (!defconfig_file)\n\t\t\tdefconfig_file = conf_get_default_confname();\n\t\tif (conf_read(defconfig_file)) {\n\t\t\tprintf(_(\"***\\n\"\n\t\t\t\t\"*** Can't find default configuration \\\"%s\\\"!\\n\"\n\t\t\t\t\"***\\n\"), defconfig_file);\n\t\t\texit(1);\n\t\t}\n\t\tbreak;\n\tcase savedefconfig:\n\tcase silentoldconfig:\n\tcase oldaskconfig:\n\tcase oldconfig:\n\tcase listnewconfig:\n\tcase olddefconfig:\n\t\tconf_read(NULL);\n\t\tbreak;\n\tcase allnoconfig:\n\tcase allyesconfig:\n\tcase allmodconfig:\n\tcase alldefconfig:\n\tcase randconfig:\n\t\tname = getenv(\"KCONFIG_ALLCONFIG\");\n\t\tif (!name)\n\t\t\tbreak;\n\t\tif ((strcmp(name, \"\") != 0) && (strcmp(name, \"1\") != 0)) {\n\t\t\tif (conf_read_simple(name, S_DEF_USER)) {\n\t\t\t\tfprintf(stderr,\n\t\t\t\t\t_(\"*** Can't read seed configuration \\\"%s\\\"!\\n\"),\n\t\t\t\t\tname);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tswitch (input_mode) {\n\t\tcase allnoconfig:\tname = \"allno.config\"; break;\n\t\tcase allyesconfig:\tname = \"allyes.config\"; break;\n\t\tcase allmodconfig:\tname = \"allmod.config\"; break;\n\t\tcase alldefconfig:\tname = \"alldef.config\"; break;\n\t\tcase randconfig:\tname = \"allrandom.config\"; break;\n\t\tdefault: break;\n\t\t}\n\t\tif (conf_read_simple(name, S_DEF_USER) &&\n\t\t    conf_read_simple(\"all.config\", S_DEF_USER)) {\n\t\t\tfprintf(stderr,\n\t\t\t\t_(\"*** KCONFIG_ALLCONFIG set, but no \\\"%s\\\" or \\\"all.config\\\" file found\\n\"),\n\t\t\t\tname);\n\t\t\texit(1);\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tif (sync_kconfig) {\n\t\tif (conf_get_changed()) {\n\t\t\tname = getenv(\"KCONFIG_NOSILENTUPDATE\");\n\t\t\tif (name && *name) {\n\t\t\t\tfprintf(stderr,\n\t\t\t\t\t_(\"\\n*** The configuration requires explicit update.\\n\\n\"));\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t\tvalid_stdin = tty_stdio;\n\t}\n\n\tswitch (input_mode) {\n\tcase allnoconfig:\n\t\tconf_set_all_new_symbols(def_no);\n\t\tbreak;\n\tcase allyesconfig:\n\t\tconf_set_all_new_symbols(def_yes);\n\t\tbreak;\n\tcase allmodconfig:\n\t\tconf_set_all_new_symbols(def_mod);\n\t\tbreak;\n\tcase alldefconfig:\n\t\tconf_set_all_new_symbols(def_default);\n\t\tbreak;\n\tcase randconfig:\n\t\t/* Really nothing to do in this loop */\n\t\twhile (conf_set_all_new_symbols(def_random)) ;\n\t\tbreak;\n\tcase defconfig:\n\t\tconf_set_all_new_symbols(def_default);\n\t\tbreak;\n\tcase savedefconfig:\n\t\tbreak;\n\tcase oldaskconfig:\n\t\trootEntry = &rootmenu;\n\t\tconf(&rootmenu);\n\t\tinput_mode = silentoldconfig;\n\t\t/* fall through */\n\tcase oldconfig:\n\tcase listnewconfig:\n\tcase olddefconfig:\n\tcase silentoldconfig:\n\t\t/* Update until a loop caused no more changes */\n\t\tdo {\n\t\t\tconf_cnt = 0;\n\t\t\tcheck_conf(&rootmenu);\n\t\t} while (conf_cnt &&\n\t\t\t (input_mode != listnewconfig &&\n\t\t\t  input_mode != olddefconfig));\n\t\tbreak;\n\t}\n\n\tif (sync_kconfig) {\n\t\t/* silentoldconfig is used during the build so we shall update autoconf.\n\t\t * All other commands are only used to generate a config.\n\t\t */\n\t\tif (conf_get_changed() && conf_write(NULL)) {\n\t\t\tfprintf(stderr, _(\"\\n*** Error during writing of the configuration.\\n\\n\"));\n\t\t\texit(1);\n\t\t}\n\t\tif (conf_write_autoconf()) {\n\t\t\tfprintf(stderr, _(\"\\n*** Error during update of the configuration.\\n\\n\"));\n\t\t\treturn 1;\n\t\t}\n\t} else if (input_mode == savedefconfig) {\n\t\tif (conf_write_defconfig(defconfig_file)) {\n\t\t\tfprintf(stderr, _(\"n*** Error while saving defconfig to: %s\\n\\n\"),\n\t\t\t        defconfig_file);\n\t\t\treturn 1;\n\t\t}\n\t} else if (input_mode != listnewconfig) {\n\t\tif (conf_write(NULL)) {\n\t\t\tfprintf(stderr, _(\"\\n*** Error during writing of the configuration.\\n\\n\"));\n\t\t\texit(1);\n\t\t}\n\t}\n\treturn 0;\n}\n\n/*\n * Helper function to facilitate fgets() by Jean Sacren.\n */\nvoid xfgets(char *str, int size, FILE *in)\n{\n\tif (fgets(str, size, in) == NULL)\n\t\tfprintf(stderr, \"\\nError in reading or end of file.\\n\");\n}\n"
  },
  {
    "path": "kconfig/confdata.c",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <sys/stat.h>\n#include <ctype.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"lkc.h\"\n\nstatic void conf_warning(const char *fmt, ...)\n\t__attribute__ ((format (printf, 1, 2)));\n\nstatic void conf_message(const char *fmt, ...)\n\t__attribute__ ((format (printf, 1, 2)));\n\nstatic const char *conf_filename;\nstatic int conf_lineno, conf_warnings, conf_unsaved;\n\nconst char conf_defname[] = \"arch/$ARCH/defconfig\";\n\nstatic void conf_warning(const char *fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s:%d:warning: \", conf_filename, conf_lineno);\n\tvfprintf(stderr, fmt, ap);\n\tfprintf(stderr, \"\\n\");\n\tva_end(ap);\n\tconf_warnings++;\n}\n\nstatic void conf_default_message_callback(const char *fmt, va_list ap)\n{\n\tprintf(\"#\\n# \");\n\tvprintf(fmt, ap);\n\tprintf(\"\\n#\\n\");\n}\n\nstatic void (*conf_message_callback) (const char *fmt, va_list ap) =\n\tconf_default_message_callback;\nvoid conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))\n{\n\tconf_message_callback = fn;\n}\n\nstatic void conf_message(const char *fmt, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tif (conf_message_callback)\n\t\tconf_message_callback(fmt, ap);\n}\n\nconst char *conf_get_configname(void)\n{\n\tchar *name = getenv(\"KCONFIG_CONFIG\");\n\n\treturn name ? name : \".config\";\n}\n\nconst char *conf_get_autoconfig_name(void)\n{\n\tchar *name = getenv(\"KCONFIG_AUTOCONFIG\");\n\n\treturn name ? name : \"include/config/auto.conf\";\n}\n\nstatic char *conf_expand_value(const char *in)\n{\n\tstruct symbol *sym;\n\tconst char *src;\n\tstatic char res_value[SYMBOL_MAXLENGTH];\n\tchar *dst, name[SYMBOL_MAXLENGTH];\n\n\tres_value[0] = 0;\n\tdst = name;\n\twhile ((src = strchr(in, '$'))) {\n\t\tstrncat(res_value, in, src - in);\n\t\tsrc++;\n\t\tdst = name;\n\t\twhile (isalnum(*src) || *src == '_')\n\t\t\t*dst++ = *src++;\n\t\t*dst = 0;\n\t\tsym = sym_lookup(name, 0);\n\t\tsym_calc_value(sym);\n\t\tstrcat(res_value, sym_get_string_value(sym));\n\t\tin = src;\n\t}\n\tstrcat(res_value, in);\n\n\treturn res_value;\n}\n\nchar *conf_get_default_confname(void)\n{\n\tstruct stat buf;\n\tstatic char fullname[PATH_MAX+1];\n\tchar *env, *name;\n\n\tname = conf_expand_value(conf_defname);\n\tenv = getenv(SRCTREE);\n\tif (env) {\n\t\tsprintf(fullname, \"%s/%s\", env, name);\n\t\tif (!stat(fullname, &buf))\n\t\t\treturn fullname;\n\t}\n\treturn name;\n}\n\nstatic int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)\n{\n\tchar *p2;\n\n\tswitch (sym->type) {\n\tcase S_TRISTATE:\n\t\tif (p[0] == 'm') {\n\t\t\tsym->def[def].tri = mod;\n\t\t\tsym->flags |= def_flags;\n\t\t\tbreak;\n\t\t}\n\t\t/* fall through */\n\tcase S_BOOLEAN:\n\t\tif (p[0] == 'y') {\n\t\t\tsym->def[def].tri = yes;\n\t\t\tsym->flags |= def_flags;\n\t\t\tbreak;\n\t\t}\n\t\tif (p[0] == 'n') {\n\t\t\tsym->def[def].tri = no;\n\t\t\tsym->flags |= def_flags;\n\t\t\tbreak;\n\t\t}\n\t\tif (def != S_DEF_AUTO)\n\t\t\tconf_warning(\"symbol value '%s' invalid for %s\",\n\t\t\t\t     p, sym->name);\n\t\treturn 1;\n\tcase S_OTHER:\n\t\tif (*p != '\"') {\n\t\t\tfor (p2 = p; *p2 && !isspace(*p2); p2++)\n\t\t\t\t;\n\t\t\tsym->type = S_STRING;\n\t\t\tgoto done;\n\t\t}\n\t\t/* fall through */\n\tcase S_STRING:\n\t\tif (*p++ != '\"')\n\t\t\tbreak;\n\t\tfor (p2 = p; (p2 = strpbrk(p2, \"\\\"\\\\\")); p2++) {\n\t\t\tif (*p2 == '\"') {\n\t\t\t\t*p2 = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmemmove(p2, p2 + 1, strlen(p2));\n\t\t}\n\t\tif (!p2) {\n\t\t\tif (def != S_DEF_AUTO)\n\t\t\t\tconf_warning(\"invalid string found\");\n\t\t\treturn 1;\n\t\t}\n\t\t/* fall through */\n\tcase S_INT:\n\tcase S_HEX:\n\tdone:\n\t\tif (sym_string_valid(sym, p)) {\n\t\t\tsym->def[def].val = strdup(p);\n\t\t\tsym->flags |= def_flags;\n\t\t} else {\n\t\t\tif (def != S_DEF_AUTO)\n\t\t\t\tconf_warning(\"symbol value '%s' invalid for %s\",\n\t\t\t\t\t     p, sym->name);\n\t\t\treturn 1;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn 0;\n}\n\n#define LINE_GROWTH 16\nstatic int add_byte(int c, char **lineptr, size_t slen, size_t *n)\n{\n\tchar *nline;\n\tsize_t new_size = slen + 1;\n\tif (new_size > *n) {\n\t\tnew_size += LINE_GROWTH - 1;\n\t\tnew_size *= 2;\n\t\tnline = realloc(*lineptr, new_size);\n\t\tif (!nline)\n\t\t\treturn -1;\n\n\t\t*lineptr = nline;\n\t\t*n = new_size;\n\t}\n\n\t(*lineptr)[slen] = c;\n\n\treturn 0;\n}\n\nstatic ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)\n{\n\tchar *line = *lineptr;\n\tsize_t slen = 0;\n\n\tfor (;;) {\n\t\tint c = getc(stream);\n\n\t\tswitch (c) {\n\t\tcase '\\n':\n\t\t\tif (add_byte(c, &line, slen, n) < 0)\n\t\t\t\tgoto e_out;\n\t\t\tslen++;\n\t\t\t/* fall through */\n\t\tcase EOF:\n\t\t\tif (add_byte('\\0', &line, slen, n) < 0)\n\t\t\t\tgoto e_out;\n\t\t\t*lineptr = line;\n\t\t\tif (slen == 0)\n\t\t\t\treturn -1;\n\t\t\treturn slen;\n\t\tdefault:\n\t\t\tif (add_byte(c, &line, slen, n) < 0)\n\t\t\t\tgoto e_out;\n\t\t\tslen++;\n\t\t}\n\t}\n\ne_out:\n\tline[slen-1] = '\\0';\n\t*lineptr = line;\n\treturn -1;\n}\n\nint conf_read_simple(const char *name, int def)\n{\n\tFILE *in = NULL;\n\tchar   *line = NULL;\n\tsize_t  line_asize = 0;\n\tchar *p, *p2;\n\tstruct symbol *sym;\n\tint i, def_flags;\n\n\tif (name) {\n\t\tin = zconf_fopen(name);\n\t} else {\n\t\tstruct property *prop;\n\n\t\tname = conf_get_configname();\n\t\tin = zconf_fopen(name);\n\t\tif (in)\n\t\t\tgoto load;\n\t\tsym_add_change_count(1);\n\t\tif (!sym_defconfig_list) {\n\t\t\tif (modules_sym)\n\t\t\t\tsym_calc_value(modules_sym);\n\t\t\treturn 1;\n\t\t}\n\n\t\tfor_all_defaults(sym_defconfig_list, prop) {\n\t\t\tif (expr_calc_value(prop->visible.expr) == no ||\n\t\t\t    prop->expr->type != E_SYMBOL)\n\t\t\t\tcontinue;\n\t\t\tname = conf_expand_value(prop->expr->left.sym->name);\n\t\t\tin = zconf_fopen(name);\n\t\t\tif (in) {\n\t\t\t\tconf_message(_(\"using defaults found in %s\"),\n\t\t\t\t\t name);\n\t\t\t\tgoto load;\n\t\t\t}\n\t\t}\n\t}\n\tif (!in)\n\t\treturn 1;\n\nload:\n\tconf_filename = name;\n\tconf_lineno = 0;\n\tconf_warnings = 0;\n\tconf_unsaved = 0;\n\n\tdef_flags = SYMBOL_DEF << def;\n\tfor_all_symbols(i, sym) {\n\t\tsym->flags |= SYMBOL_CHANGED;\n\t\tsym->flags &= ~(def_flags|SYMBOL_VALID);\n\t\tif (sym_is_choice(sym))\n\t\t\tsym->flags |= def_flags;\n\t\tswitch (sym->type) {\n\t\tcase S_INT:\n\t\tcase S_HEX:\n\t\tcase S_STRING:\n\t\t\tif (sym->def[def].val)\n\t\t\t\tfree(sym->def[def].val);\n\t\t\t/* fall through */\n\t\tdefault:\n\t\t\tsym->def[def].val = NULL;\n\t\t\tsym->def[def].tri = no;\n\t\t}\n\t}\n\n\twhile (compat_getline(&line, &line_asize, in) != -1) {\n\t\tconf_lineno++;\n\t\tsym = NULL;\n\t\tif (line[0] == '#') {\n\t\t\tif (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))\n\t\t\t\tcontinue;\n\t\t\tp = strchr(line + 2 + strlen(CONFIG_), ' ');\n\t\t\tif (!p)\n\t\t\t\tcontinue;\n\t\t\t*p++ = 0;\n\t\t\tif (strncmp(p, \"is not set\", 10))\n\t\t\t\tcontinue;\n\t\t\tif (def == S_DEF_USER) {\n\t\t\t\tsym = sym_find(line + 2 + strlen(CONFIG_));\n\t\t\t\tif (!sym) {\n\t\t\t\t\tsym_add_change_count(1);\n\t\t\t\t\tgoto setsym;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsym = sym_lookup(line + 2 + strlen(CONFIG_), 0);\n\t\t\t\tif (sym->type == S_UNKNOWN)\n\t\t\t\t\tsym->type = S_BOOLEAN;\n\t\t\t}\n\t\t\tif (sym->flags & def_flags) {\n\t\t\t\tconf_warning(\"override: reassigning to symbol %s\", sym->name);\n\t\t\t}\n\t\t\tswitch (sym->type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\tcase S_TRISTATE:\n\t\t\t\tsym->def[def].tri = no;\n\t\t\t\tsym->flags |= def_flags;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t;\n\t\t\t}\n\t\t} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {\n\t\t\tp = strchr(line + strlen(CONFIG_), '=');\n\t\t\tif (!p)\n\t\t\t\tcontinue;\n\t\t\t*p++ = 0;\n\t\t\tp2 = strchr(p, '\\n');\n\t\t\tif (p2) {\n\t\t\t\t*p2-- = 0;\n\t\t\t\tif (*p2 == '\\r')\n\t\t\t\t\t*p2 = 0;\n\t\t\t}\n\t\t\tif (def == S_DEF_USER) {\n\t\t\t\tsym = sym_find(line + strlen(CONFIG_));\n\t\t\t\tif (!sym) {\n\t\t\t\t\tsym_add_change_count(1);\n\t\t\t\t\tgoto setsym;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsym = sym_lookup(line + strlen(CONFIG_), 0);\n\t\t\t\tif (sym->type == S_UNKNOWN)\n\t\t\t\t\tsym->type = S_OTHER;\n\t\t\t}\n\t\t\tif (sym->flags & def_flags) {\n\t\t\t\tconf_warning(\"override: reassigning to symbol %s\", sym->name);\n\t\t\t}\n\t\t\tif (conf_set_sym_val(sym, def, def_flags, p))\n\t\t\t\tcontinue;\n\t\t} else {\n\t\t\tif (line[0] != '\\r' && line[0] != '\\n')\n\t\t\t\tconf_warning(\"unexpected data\");\n\t\t\tcontinue;\n\t\t}\nsetsym:\n\t\tif (sym && sym_is_choice_value(sym)) {\n\t\t\tstruct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));\n\t\t\tswitch (sym->def[def].tri) {\n\t\t\tcase no:\n\t\t\t\tbreak;\n\t\t\tcase mod:\n\t\t\t\tif (cs->def[def].tri == yes) {\n\t\t\t\t\tconf_warning(\"%s creates inconsistent choice state\", sym->name);\n\t\t\t\t\tcs->flags &= ~def_flags;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase yes:\n\t\t\t\tif (cs->def[def].tri != no)\n\t\t\t\t\tconf_warning(\"override: %s changes choice state\", sym->name);\n\t\t\t\tcs->def[def].val = sym;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);\n\t\t}\n\t}\n\tfree(line);\n\tfclose(in);\n\n\tif (modules_sym)\n\t\tsym_calc_value(modules_sym);\n\treturn 0;\n}\n\nint conf_read(const char *name)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tsym_set_change_count(0);\n\n\tif (conf_read_simple(name, S_DEF_USER))\n\t\treturn 1;\n\n\tfor_all_symbols(i, sym) {\n\t\tsym_calc_value(sym);\n\t\tif (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))\n\t\t\tcontinue;\n\t\tif (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {\n\t\t\t/* check that calculated value agrees with saved value */\n\t\t\tswitch (sym->type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\tcase S_TRISTATE:\n\t\t\t\tif (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))\n\t\t\t\t\tbreak;\n\t\t\t\tif (!sym_is_choice(sym))\n\t\t\t\t\tcontinue;\n\t\t\t\t/* fall through */\n\t\t\tdefault:\n\t\t\t\tif (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))\n\t\t\t\t\tcontinue;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))\n\t\t\t/* no previous value and not saved */\n\t\t\tcontinue;\n\t\tconf_unsaved++;\n\t\t/* maybe print value in verbose mode... */\n\t}\n\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_has_value(sym) && !sym_is_choice_value(sym)) {\n\t\t\t/* Reset values of generates values, so they'll appear\n\t\t\t * as new, if they should become visible, but that\n\t\t\t * doesn't quite work if the Kconfig and the saved\n\t\t\t * configuration disagree.\n\t\t\t */\n\t\t\tif (sym->visible == no && !conf_unsaved)\n\t\t\t\tsym->flags &= ~SYMBOL_DEF_USER;\n\t\t\tswitch (sym->type) {\n\t\t\tcase S_STRING:\n\t\t\tcase S_INT:\n\t\t\tcase S_HEX:\n\t\t\t\t/* Reset a string value if it's out of range */\n\t\t\t\tif (sym_string_within_range(sym, sym->def[S_DEF_USER].val))\n\t\t\t\t\tbreak;\n\t\t\t\tsym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);\n\t\t\t\tconf_unsaved++;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tsym_add_change_count(conf_warnings || conf_unsaved);\n\n\treturn 0;\n}\n\n/*\n * Kconfig configuration printer\n *\n * This printer is used when generating the resulting configuration after\n * kconfig invocation and `defconfig' files. Unset symbol might be omitted by\n * passing a non-NULL argument to the printer.\n *\n */\nstatic void\nkconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)\n{\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tif (*value == 'n') {\n\t\t\tbool skip_unset = (arg != NULL);\n\n\t\t\tif (!skip_unset)\n\t\t\t\tfprintf(fp, \"# %s%s is not set\\n\",\n\t\t\t\t    CONFIG_, sym->name);\n\t\t\treturn;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tfprintf(fp, \"%s%s=%s\\n\", CONFIG_, sym->name, value);\n}\n\nstatic void\nkconfig_print_comment(FILE *fp, const char *value, void *arg)\n{\n\tconst char *p = value;\n\tsize_t l;\n\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\n\");\n\t\tfprintf(fp, \"#\");\n\t\tif (l) {\n\t\t\tfprintf(fp, \" \");\n\t\t\txfwrite(p, l, 1, fp);\n\t\t\tp += l;\n\t\t}\n\t\tfprintf(fp, \"\\n\");\n\t\tif (*p++ == '\\0')\n\t\t\tbreak;\n\t}\n}\n\nstatic struct conf_printer kconfig_printer_cb =\n{\n\t.print_symbol = kconfig_print_symbol,\n\t.print_comment = kconfig_print_comment,\n};\n\n/*\n * Header printer\n *\n * This printer is used when generating the `include/generated/autoconf.h' file.\n */\nstatic void\nheader_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)\n{\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE: {\n\t\tconst char *suffix = \"\";\n\n\t\tswitch (*value) {\n\t\tcase 'n':\n\t\t\tbreak;\n\t\tcase 'm':\n\t\t\tsuffix = \"_MODULE\";\n\t\t\t/* fall through */\n\t\tdefault:\n\t\t\tfprintf(fp, \"#define %s%s%s 1\\n\",\n\t\t\t    CONFIG_, sym->name, suffix);\n\t\t}\n\t\tbreak;\n\t}\n\tcase S_HEX: {\n\t\tconst char *prefix = \"\";\n\n\t\tif (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))\n\t\t\tprefix = \"0x\";\n\t\tfprintf(fp, \"#define %s%s %s%s\\n\",\n\t\t    CONFIG_, sym->name, prefix, value);\n\t\tbreak;\n\t}\n\tcase S_STRING:\n\tcase S_INT:\n\t\tfprintf(fp, \"#define %s%s %s\\n\",\n\t\t    CONFIG_, sym->name, value);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n}\n\nstatic void\nheader_print_comment(FILE *fp, const char *value, void *arg)\n{\n\tconst char *p = value;\n\tsize_t l;\n\n\tfprintf(fp, \"/*\\n\");\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\n\");\n\t\tfprintf(fp, \" *\");\n\t\tif (l) {\n\t\t\tfprintf(fp, \" \");\n\t\t\txfwrite(p, l, 1, fp);\n\t\t\tp += l;\n\t\t}\n\t\tfprintf(fp, \"\\n\");\n\t\tif (*p++ == '\\0')\n\t\t\tbreak;\n\t}\n\tfprintf(fp, \" */\\n\");\n}\n\nstatic struct conf_printer header_printer_cb =\n{\n\t.print_symbol = header_print_symbol,\n\t.print_comment = header_print_comment,\n};\n\n/*\n * Tristate printer\n *\n * This printer is used when generating the `include/config/tristate.conf' file.\n */\nstatic void\ntristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)\n{\n\n\tif (sym->type == S_TRISTATE && *value != 'n')\n\t\tfprintf(fp, \"%s%s=%c\\n\", CONFIG_, sym->name, (char)toupper(*value));\n}\n\nstatic struct conf_printer tristate_printer_cb =\n{\n\t.print_symbol = tristate_print_symbol,\n\t.print_comment = kconfig_print_comment,\n};\n\nstatic void conf_write_symbol(FILE *fp, struct symbol *sym,\n\t\t\t      struct conf_printer *printer, void *printer_arg)\n{\n\tconst char *str;\n\n\tswitch (sym->type) {\n\tcase S_OTHER:\n\tcase S_UNKNOWN:\n\t\tbreak;\n\tcase S_STRING:\n\t\tstr = sym_get_string_value(sym);\n\t\tstr = sym_escape_string_value(str);\n\t\tprinter->print_symbol(fp, sym, str, printer_arg);\n\t\tfree((void *)str);\n\t\tbreak;\n\tdefault:\n\t\tstr = sym_get_string_value(sym);\n\t\tprinter->print_symbol(fp, sym, str, printer_arg);\n\t}\n}\n\nstatic void\nconf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)\n{\n\tchar buf[256];\n\n\tsnprintf(buf, sizeof(buf),\n\t    \"\\n\"\n\t    \"Automatically generated file; DO NOT EDIT.\\n\"\n\t    \"%s\\n\",\n\t    rootmenu.prompt->text);\n\n\tprinter->print_comment(fp, buf, printer_arg);\n}\n\n/*\n * Write out a minimal config.\n * All values that has default values are skipped as this is redundant.\n */\nint conf_write_defconfig(const char *filename)\n{\n\tstruct symbol *sym;\n\tstruct menu *menu;\n\tFILE *out;\n\n\tout = fopen(filename, \"w\");\n\tif (!out)\n\t\treturn 1;\n\n\tsym_clear_all_valid();\n\n\t/* Traverse all menus to find all relevant symbols */\n\tmenu = rootmenu.list;\n\n\twhile (menu != NULL)\n\t{\n\t\tsym = menu->sym;\n\t\tif (sym == NULL) {\n\t\t\tif (!menu_is_visible(menu))\n\t\t\t\tgoto next_menu;\n\t\t} else if (!sym_is_choice(sym)) {\n\t\t\tsym_calc_value(sym);\n\t\t\tif (!(sym->flags & SYMBOL_WRITE))\n\t\t\t\tgoto next_menu;\n\t\t\tsym->flags &= ~SYMBOL_WRITE;\n\t\t\t/* If we cannot change the symbol - skip */\n\t\t\tif (!sym_is_changable(sym))\n\t\t\t\tgoto next_menu;\n\t\t\t/* If symbol equals to default value - skip */\n\t\t\tif (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)\n\t\t\t\tgoto next_menu;\n\n\t\t\t/*\n\t\t\t * If symbol is a choice value and equals to the\n\t\t\t * default for a choice - skip.\n\t\t\t * But only if value is bool and equal to \"y\" and\n\t\t\t * choice is not \"optional\".\n\t\t\t * (If choice is \"optional\" then all values can be \"n\")\n\t\t\t */\n\t\t\tif (sym_is_choice_value(sym)) {\n\t\t\t\tstruct symbol *cs;\n\t\t\t\tstruct symbol *ds;\n\n\t\t\t\tcs = prop_get_symbol(sym_get_choice_prop(sym));\n\t\t\t\tds = sym_choice_default(cs);\n\t\t\t\tif (!sym_is_optional(cs) && sym == ds) {\n\t\t\t\t\tif ((sym->type == S_BOOLEAN) &&\n\t\t\t\t\t    sym_get_tristate_value(sym) == yes)\n\t\t\t\t\t\tgoto next_menu;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconf_write_symbol(out, sym, &kconfig_printer_cb, NULL);\n\t\t}\nnext_menu:\n\t\tif (menu->list != NULL) {\n\t\t\tmenu = menu->list;\n\t\t}\n\t\telse if (menu->next != NULL) {\n\t\t\tmenu = menu->next;\n\t\t} else {\n\t\t\twhile ((menu = menu->parent)) {\n\t\t\t\tif (menu->next != NULL) {\n\t\t\t\t\tmenu = menu->next;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfclose(out);\n\treturn 0;\n}\n\nint conf_write(const char *name)\n{\n\tFILE *out;\n\tstruct symbol *sym;\n\tstruct menu *menu;\n\tconst char *basename;\n\tconst char *str;\n\tchar dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];\n\tchar *env;\n\n\tdirname[0] = 0;\n\tif (name && name[0]) {\n\t\tstruct stat st;\n\t\tchar *slash;\n\n\t\tif (!stat(name, &st) && S_ISDIR(st.st_mode)) {\n\t\t\tstrcpy(dirname, name);\n\t\t\tstrcat(dirname, \"/\");\n\t\t\tbasename = conf_get_configname();\n\t\t} else if ((slash = strrchr(name, '/'))) {\n\t\t\tint size = slash - name + 1;\n\t\t\tmemcpy(dirname, name, size);\n\t\t\tdirname[size] = 0;\n\t\t\tif (slash[1])\n\t\t\t\tbasename = slash + 1;\n\t\t\telse\n\t\t\t\tbasename = conf_get_configname();\n\t\t} else\n\t\t\tbasename = name;\n\t} else\n\t\tbasename = conf_get_configname();\n\n\tsprintf(newname, \"%s%s\", dirname, basename);\n\tenv = getenv(\"KCONFIG_OVERWRITECONFIG\");\n\tif (!env || !*env) {\n\t\tsprintf(tmpname, \"%s.tmpconfig.%d\", dirname, (int)getpid());\n\t\tout = fopen(tmpname, \"w\");\n\t} else {\n\t\t*tmpname = 0;\n\t\tout = fopen(newname, \"w\");\n\t}\n\tif (!out)\n\t\treturn 1;\n\n\tconf_write_heading(out, &kconfig_printer_cb, NULL);\n\n\tif (!conf_get_changed())\n\t\tsym_clear_all_valid();\n\n\tmenu = rootmenu.list;\n\twhile (menu) {\n\t\tsym = menu->sym;\n\t\tif (!sym) {\n\t\t\tif (!menu_is_visible(menu))\n\t\t\t\tgoto next;\n\t\t\tstr = menu_get_prompt(menu);\n\t\t\tfprintf(out, \"\\n\"\n\t\t\t\t     \"#\\n\"\n\t\t\t\t     \"# %s\\n\"\n\t\t\t\t     \"#\\n\", str);\n\t\t} else if (!(sym->flags & SYMBOL_CHOICE)) {\n\t\t\tsym_calc_value(sym);\n\t\t\tif (!(sym->flags & SYMBOL_WRITE))\n\t\t\t\tgoto next;\n\t\t\tsym->flags &= ~SYMBOL_WRITE;\n\n\t\t\tconf_write_symbol(out, sym, &kconfig_printer_cb, NULL);\n\t\t}\n\nnext:\n\t\tif (menu->list) {\n\t\t\tmenu = menu->list;\n\t\t\tcontinue;\n\t\t}\n\t\tif (menu->next)\n\t\t\tmenu = menu->next;\n\t\telse while ((menu = menu->parent)) {\n\t\t\tif (menu->next) {\n\t\t\t\tmenu = menu->next;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tfclose(out);\n\n\tif (*tmpname) {\n\t\tstrcat(dirname, basename);\n\t\tstrcat(dirname, \".old\");\n\t\trename(newname, dirname);\n\t\tif (rename(tmpname, newname))\n\t\t\treturn 1;\n\t}\n\n\tconf_message(_(\"configuration written to %s\"), newname);\n\n\tsym_set_change_count(0);\n\n\treturn 0;\n}\n\nstatic int conf_split_config(void)\n{\n\tconst char *name;\n\tchar path[PATH_MAX+1];\n\tchar *s, *d, c;\n\tstruct symbol *sym;\n\tstruct stat sb;\n\tint res, i, fd;\n\n\tname = conf_get_autoconfig_name();\n\tconf_read_simple(name, S_DEF_AUTO);\n\n\tif (chdir(\"include/config\"))\n\t\treturn 1;\n\n\tres = 0;\n\tfor_all_symbols(i, sym) {\n\t\tsym_calc_value(sym);\n\t\tif ((sym->flags & SYMBOL_AUTO) || !sym->name)\n\t\t\tcontinue;\n\t\tif (sym->flags & SYMBOL_WRITE) {\n\t\t\tif (sym->flags & SYMBOL_DEF_AUTO) {\n\t\t\t\t/*\n\t\t\t\t * symbol has old and new value,\n\t\t\t\t * so compare them...\n\t\t\t\t */\n\t\t\t\tswitch (sym->type) {\n\t\t\t\tcase S_BOOLEAN:\n\t\t\t\tcase S_TRISTATE:\n\t\t\t\t\tif (sym_get_tristate_value(sym) ==\n\t\t\t\t\t    sym->def[S_DEF_AUTO].tri)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S_STRING:\n\t\t\t\tcase S_HEX:\n\t\t\t\tcase S_INT:\n\t\t\t\t\tif (!strcmp(sym_get_string_value(sym),\n\t\t\t\t\t\t    sym->def[S_DEF_AUTO].val))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * If there is no old value, only 'no' (unset)\n\t\t\t\t * is allowed as new value.\n\t\t\t\t */\n\t\t\t\tswitch (sym->type) {\n\t\t\t\tcase S_BOOLEAN:\n\t\t\t\tcase S_TRISTATE:\n\t\t\t\t\tif (sym_get_tristate_value(sym) == no)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (!(sym->flags & SYMBOL_DEF_AUTO))\n\t\t\t/* There is neither an old nor a new value. */\n\t\t\tcontinue;\n\t\t/* else\n\t\t *\tThere is an old value, but no new value ('no' (unset)\n\t\t *\tisn't saved in auto.conf, so the old value is always\n\t\t *\tdifferent from 'no').\n\t\t */\n\n\t\t/* Replace all '_' and append \".h\" */\n\t\ts = sym->name;\n\t\td = path;\n\t\twhile ((c = *s++)) {\n\t\t\tc = tolower(c);\n\t\t\t*d++ = (c == '_') ? '/' : c;\n\t\t}\n\t\tstrcpy(d, \".h\");\n\n\t\t/* Assume directory path already exists. */\n\t\tfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);\n\t\tif (fd == -1) {\n\t\t\tif (errno != ENOENT) {\n\t\t\t\tres = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/*\n\t\t\t * Create directory components,\n\t\t\t * unless they exist already.\n\t\t\t */\n\t\t\td = path;\n\t\t\twhile ((d = strchr(d, '/'))) {\n\t\t\t\t*d = 0;\n\t\t\t\tif (stat(path, &sb) && mkdir(path, 0755)) {\n\t\t\t\t\tres = 1;\n\t\t\t\t\tgoto out;\n\t\t\t\t}\n\t\t\t\t*d++ = '/';\n\t\t\t}\n\t\t\t/* Try it again. */\n\t\t\tfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);\n\t\t\tif (fd == -1) {\n\t\t\t\tres = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tclose(fd);\n\t}\nout:\n\tif (chdir(\"../..\"))\n\t\treturn 1;\n\n\treturn res;\n}\n\nint conf_write_autoconf(void)\n{\n\tstruct symbol *sym;\n\tconst char *name;\n\tFILE *out, *tristate, *out_h;\n\tint i;\n\n\tsym_clear_all_valid();\n\n\tfile_write_dep(\"include/config/auto.conf.cmd\");\n\n\tif (conf_split_config())\n\t\treturn 1;\n\n\tout = fopen(\".tmpconfig\", \"w\");\n\tif (!out)\n\t\treturn 1;\n\n\ttristate = fopen(\".tmpconfig_tristate\", \"w\");\n\tif (!tristate) {\n\t\tfclose(out);\n\t\treturn 1;\n\t}\n\n\tout_h = fopen(\".tmpconfig.h\", \"w\");\n\tif (!out_h) {\n\t\tfclose(out);\n\t\tfclose(tristate);\n\t\treturn 1;\n\t}\n\n\tconf_write_heading(out, &kconfig_printer_cb, NULL);\n\n\tconf_write_heading(tristate, &tristate_printer_cb, NULL);\n\n\tconf_write_heading(out_h, &header_printer_cb, NULL);\n\n\tfor_all_symbols(i, sym) {\n\t\tsym_calc_value(sym);\n\t\tif (!(sym->flags & SYMBOL_WRITE) || !sym->name)\n\t\t\tcontinue;\n\n\t\t/* write symbol to auto.conf, tristate and header files */\n\t\tconf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);\n\n\t\tconf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);\n\n\t\tconf_write_symbol(out_h, sym, &header_printer_cb, NULL);\n\t}\n\tfclose(out);\n\tfclose(tristate);\n\tfclose(out_h);\n\n\tname = getenv(\"KCONFIG_AUTOHEADER\");\n\tif (!name)\n\t\tname = \"include/generated/autoconf.h\";\n\tif (rename(\".tmpconfig.h\", name))\n\t\treturn 1;\n\tname = getenv(\"KCONFIG_TRISTATE\");\n\tif (!name)\n\t\tname = \"include/config/tristate.conf\";\n\tif (rename(\".tmpconfig_tristate\", name))\n\t\treturn 1;\n\tname = conf_get_autoconfig_name();\n\t/*\n\t * This must be the last step, kbuild has a dependency on auto.conf\n\t * and this marks the successful completion of the previous steps.\n\t */\n\tif (rename(\".tmpconfig\", name))\n\t\treturn 1;\n\n\treturn 0;\n}\n\nstatic int sym_change_count;\nstatic void (*conf_changed_callback)(void);\n\nvoid sym_set_change_count(int count)\n{\n\tint _sym_change_count = sym_change_count;\n\tsym_change_count = count;\n\tif (conf_changed_callback &&\n\t    (bool)_sym_change_count != (bool)count)\n\t\tconf_changed_callback();\n}\n\nvoid sym_add_change_count(int count)\n{\n\tsym_set_change_count(count + sym_change_count);\n}\n\nbool conf_get_changed(void)\n{\n\treturn sym_change_count;\n}\n\nvoid conf_set_changed_callback(void (*fn)(void))\n{\n\tconf_changed_callback = fn;\n}\n\nstatic bool randomize_choice_values(struct symbol *csym)\n{\n\tstruct property *prop;\n\tstruct symbol *sym;\n\tstruct expr *e;\n\tint cnt, def;\n\n\t/*\n\t * If choice is mod then we may have more items selected\n\t * and if no then no-one.\n\t * In both cases stop.\n\t */\n\tif (csym->curr.tri != yes)\n\t\treturn false;\n\n\tprop = sym_get_choice_prop(csym);\n\n\t/* count entries in choice block */\n\tcnt = 0;\n\texpr_list_for_each_sym(prop->expr, e, sym)\n\t\tcnt++;\n\n\t/*\n\t * find a random value and set it to yes,\n\t * set the rest to no so we have only one set\n\t */\n\tdef = (rand() % cnt);\n\n\tcnt = 0;\n\texpr_list_for_each_sym(prop->expr, e, sym) {\n\t\tif (def == cnt++) {\n\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\tcsym->def[S_DEF_USER].val = sym;\n\t\t}\n\t\telse {\n\t\t\tsym->def[S_DEF_USER].tri = no;\n\t\t}\n\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\t/* clear VALID to get value calculated */\n\t\tsym->flags &= ~SYMBOL_VALID;\n\t}\n\tcsym->flags |= SYMBOL_DEF_USER;\n\t/* clear VALID to get value calculated */\n\tcsym->flags &= ~(SYMBOL_VALID);\n\n\treturn true;\n}\n\nvoid set_all_choice_values(struct symbol *csym)\n{\n\tstruct property *prop;\n\tstruct symbol *sym;\n\tstruct expr *e;\n\n\tprop = sym_get_choice_prop(csym);\n\n\t/*\n\t * Set all non-assinged choice values to no\n\t */\n\texpr_list_for_each_sym(prop->expr, e, sym) {\n\t\tif (!sym_has_value(sym))\n\t\t\tsym->def[S_DEF_USER].tri = no;\n\t}\n\tcsym->flags |= SYMBOL_DEF_USER;\n\t/* clear VALID to get value calculated */\n\tcsym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);\n}\n\nbool conf_set_all_new_symbols(enum conf_def_mode mode)\n{\n\tstruct symbol *sym, *csym;\n\tint i, cnt, pby, pty, ptm;\t/* pby: probability of boolean  = y\n\t\t\t\t\t * pty: probability of tristate = y\n\t\t\t\t\t * ptm: probability of tristate = m\n\t\t\t\t\t */\n\n\tpby = 50; pty = ptm = 33; /* can't go as the default in switch-case\n\t\t\t\t   * below, otherwise gcc whines about\n\t\t\t\t   * -Wmaybe-uninitialized */\n\tif (mode == def_random) {\n\t\tint n, p[3];\n\t\tchar *env = getenv(\"KCONFIG_PROBABILITY\");\n\t\tn = 0;\n\t\twhile( env && *env ) {\n\t\t\tchar *endp;\n\t\t\tint tmp = strtol( env, &endp, 10 );\n\t\t\tif( tmp >= 0 && tmp <= 100 ) {\n\t\t\t\tp[n++] = tmp;\n\t\t\t} else {\n\t\t\t\terrno = ERANGE;\n\t\t\t\tperror( \"KCONFIG_PROBABILITY\" );\n\t\t\t\texit( 1 );\n\t\t\t}\n\t\t\tenv = (*endp == ':') ? endp+1 : endp;\n\t\t\tif( n >=3 ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tswitch( n ) {\n\t\tcase 1:\n\t\t\tpby = p[0]; ptm = pby/2; pty = pby-ptm;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tpty = p[0]; ptm = p[1]; pby = pty + ptm;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tpby = p[0]; pty = p[1]; ptm = p[2];\n\t\t\tbreak;\n\t\t}\n\n\t\tif( pty+ptm > 100 ) {\n\t\t\terrno = ERANGE;\n\t\t\tperror( \"KCONFIG_PROBABILITY\" );\n\t\t\texit( 1 );\n\t\t}\n\t}\n\tbool has_changed = false;\n\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))\n\t\t\tcontinue;\n\t\tswitch (sym_get_type(sym)) {\n\t\tcase S_BOOLEAN:\n\t\tcase S_TRISTATE:\n\t\t\thas_changed = true;\n\t\t\tswitch (mode) {\n\t\t\tcase def_yes:\n\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\tbreak;\n\t\t\tcase def_mod:\n\t\t\t\tsym->def[S_DEF_USER].tri = mod;\n\t\t\t\tbreak;\n\t\t\tcase def_no:\n\t\t\t\tif (sym->flags & SYMBOL_ALLNOCONFIG_Y)\n\t\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\telse\n\t\t\t\t\tsym->def[S_DEF_USER].tri = no;\n\t\t\t\tbreak;\n\t\t\tcase def_random:\n\t\t\t\tsym->def[S_DEF_USER].tri = no;\n\t\t\t\tcnt = rand() % 100;\n\t\t\t\tif (sym->type == S_TRISTATE) {\n\t\t\t\t\tif (cnt < pty)\n\t\t\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\t\telse if (cnt < (pty+ptm))\n\t\t\t\t\t\tsym->def[S_DEF_USER].tri = mod;\n\t\t\t\t} else if (cnt < pby)\n\t\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(sym_is_choice(sym) && mode == def_random))\n\t\t\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n\tsym_clear_all_valid();\n\n\t/*\n\t * We have different type of choice blocks.\n\t * If curr.tri equals to mod then we can select several\n\t * choice symbols in one block.\n\t * In this case we do nothing.\n\t * If curr.tri equals yes then only one symbol can be\n\t * selected in a choice block and we set it to yes,\n\t * and the rest to no.\n\t */\n\tif (mode != def_random) {\n\t\tfor_all_symbols(i, csym) {\n\t\t\tif ((sym_is_choice(csym) && !sym_has_value(csym)) ||\n\t\t\t    sym_is_choice_value(csym))\n\t\t\t\tcsym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;\n\t\t}\n\t}\n\n\tfor_all_symbols(i, csym) {\n\t\tif (sym_has_value(csym) || !sym_is_choice(csym))\n\t\t\tcontinue;\n\n\t\tsym_calc_value(csym);\n\t\tif (mode == def_random)\n\t\t\thas_changed = randomize_choice_values(csym);\n\t\telse {\n\t\t\tset_all_choice_values(csym);\n\t\t\thas_changed = true;\n\t\t}\n\t}\n\n\treturn has_changed;\n}\n"
  },
  {
    "path": "kconfig/expr.c",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"lkc.h\"\n\n#define DEBUG_EXPR\t0\n\nstruct expr *expr_alloc_symbol(struct symbol *sym)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = E_SYMBOL;\n\te->left.sym = sym;\n\treturn e;\n}\n\nstruct expr *expr_alloc_one(enum expr_type type, struct expr *ce)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = type;\n\te->left.expr = ce;\n\treturn e;\n}\n\nstruct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = type;\n\te->left.expr = e1;\n\te->right.expr = e2;\n\treturn e;\n}\n\nstruct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = type;\n\te->left.sym = s1;\n\te->right.sym = s2;\n\treturn e;\n}\n\nstruct expr *expr_alloc_and(struct expr *e1, struct expr *e2)\n{\n\tif (!e1)\n\t\treturn e2;\n\treturn e2 ? expr_alloc_two(E_AND, e1, e2) : e1;\n}\n\nstruct expr *expr_alloc_or(struct expr *e1, struct expr *e2)\n{\n\tif (!e1)\n\t\treturn e2;\n\treturn e2 ? expr_alloc_two(E_OR, e1, e2) : e1;\n}\n\nstruct expr *expr_copy(const struct expr *org)\n{\n\tstruct expr *e;\n\n\tif (!org)\n\t\treturn NULL;\n\n\te = xmalloc(sizeof(*org));\n\tmemcpy(e, org, sizeof(*org));\n\tswitch (org->type) {\n\tcase E_SYMBOL:\n\t\te->left = org->left;\n\t\tbreak;\n\tcase E_NOT:\n\t\te->left.expr = expr_copy(org->left.expr);\n\t\tbreak;\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\t\te->left.sym = org->left.sym;\n\t\te->right.sym = org->right.sym;\n\t\tbreak;\n\tcase E_AND:\n\tcase E_OR:\n\tcase E_LIST:\n\t\te->left.expr = expr_copy(org->left.expr);\n\t\te->right.expr = expr_copy(org->right.expr);\n\t\tbreak;\n\tdefault:\n\t\tprintf(\"can't copy type %d\\n\", e->type);\n\t\tfree(e);\n\t\te = NULL;\n\t\tbreak;\n\t}\n\n\treturn e;\n}\n\nvoid expr_free(struct expr *e)\n{\n\tif (!e)\n\t\treturn;\n\n\tswitch (e->type) {\n\tcase E_SYMBOL:\n\t\tbreak;\n\tcase E_NOT:\n\t\texpr_free(e->left.expr);\n\t\treturn;\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\t\tbreak;\n\tcase E_OR:\n\tcase E_AND:\n\t\texpr_free(e->left.expr);\n\t\texpr_free(e->right.expr);\n\t\tbreak;\n\tdefault:\n\t\tprintf(\"how to free type %d?\\n\", e->type);\n\t\tbreak;\n\t}\n\tfree(e);\n}\n\nstatic int trans_count;\n\n#define e1 (*ep1)\n#define e2 (*ep2)\n\nstatic void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)\n{\n\tif (e1->type == type) {\n\t\t__expr_eliminate_eq(type, &e1->left.expr, &e2);\n\t\t__expr_eliminate_eq(type, &e1->right.expr, &e2);\n\t\treturn;\n\t}\n\tif (e2->type == type) {\n\t\t__expr_eliminate_eq(type, &e1, &e2->left.expr);\n\t\t__expr_eliminate_eq(type, &e1, &e2->right.expr);\n\t\treturn;\n\t}\n\tif (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&\n\t    e1->left.sym == e2->left.sym &&\n\t    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))\n\t\treturn;\n\tif (!expr_eq(e1, e2))\n\t\treturn;\n\ttrans_count++;\n\texpr_free(e1); expr_free(e2);\n\tswitch (type) {\n\tcase E_OR:\n\t\te1 = expr_alloc_symbol(&symbol_no);\n\t\te2 = expr_alloc_symbol(&symbol_no);\n\t\tbreak;\n\tcase E_AND:\n\t\te1 = expr_alloc_symbol(&symbol_yes);\n\t\te2 = expr_alloc_symbol(&symbol_yes);\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n}\n\nvoid expr_eliminate_eq(struct expr **ep1, struct expr **ep2)\n{\n\tif (!e1 || !e2)\n\t\treturn;\n\tswitch (e1->type) {\n\tcase E_OR:\n\tcase E_AND:\n\t\t__expr_eliminate_eq(e1->type, ep1, ep2);\n\tdefault:\n\t\t;\n\t}\n\tif (e1->type != e2->type) switch (e2->type) {\n\tcase E_OR:\n\tcase E_AND:\n\t\t__expr_eliminate_eq(e2->type, ep1, ep2);\n\tdefault:\n\t\t;\n\t}\n\te1 = expr_eliminate_yn(e1);\n\te2 = expr_eliminate_yn(e2);\n}\n\n#undef e1\n#undef e2\n\nint expr_eq(struct expr *e1, struct expr *e2)\n{\n\tint res, old_count;\n\n\tif (e1->type != e2->type)\n\t\treturn 0;\n\tswitch (e1->type) {\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\t\treturn e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;\n\tcase E_SYMBOL:\n\t\treturn e1->left.sym == e2->left.sym;\n\tcase E_NOT:\n\t\treturn expr_eq(e1->left.expr, e2->left.expr);\n\tcase E_AND:\n\tcase E_OR:\n\t\te1 = expr_copy(e1);\n\t\te2 = expr_copy(e2);\n\t\told_count = trans_count;\n\t\texpr_eliminate_eq(&e1, &e2);\n\t\tres = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&\n\t\t       e1->left.sym == e2->left.sym);\n\t\texpr_free(e1);\n\t\texpr_free(e2);\n\t\ttrans_count = old_count;\n\t\treturn res;\n\tcase E_LIST:\n\tcase E_RANGE:\n\tcase E_NONE:\n\t\t/* panic */;\n\t}\n\n\tif (DEBUG_EXPR) {\n\t\texpr_fprint(e1, stdout);\n\t\tprintf(\" = \");\n\t\texpr_fprint(e2, stdout);\n\t\tprintf(\" ?\\n\");\n\t}\n\n\treturn 0;\n}\n\nstruct expr *expr_eliminate_yn(struct expr *e)\n{\n\tstruct expr *tmp;\n\n\tif (e) switch (e->type) {\n\tcase E_AND:\n\t\te->left.expr = expr_eliminate_yn(e->left.expr);\n\t\te->right.expr = expr_eliminate_yn(e->right.expr);\n\t\tif (e->left.expr->type == E_SYMBOL) {\n\t\t\tif (e->left.expr->left.sym == &symbol_no) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_no;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t} else if (e->left.expr->left.sym == &symbol_yes) {\n\t\t\t\tfree(e->left.expr);\n\t\t\t\ttmp = e->right.expr;\n\t\t\t\t*e = *(e->right.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tif (e->right.expr->type == E_SYMBOL) {\n\t\t\tif (e->right.expr->left.sym == &symbol_no) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_no;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t} else if (e->right.expr->left.sym == &symbol_yes) {\n\t\t\t\tfree(e->right.expr);\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\t*e = *(e->left.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase E_OR:\n\t\te->left.expr = expr_eliminate_yn(e->left.expr);\n\t\te->right.expr = expr_eliminate_yn(e->right.expr);\n\t\tif (e->left.expr->type == E_SYMBOL) {\n\t\t\tif (e->left.expr->left.sym == &symbol_no) {\n\t\t\t\tfree(e->left.expr);\n\t\t\t\ttmp = e->right.expr;\n\t\t\t\t*e = *(e->right.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t} else if (e->left.expr->left.sym == &symbol_yes) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_yes;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tif (e->right.expr->type == E_SYMBOL) {\n\t\t\tif (e->right.expr->left.sym == &symbol_no) {\n\t\t\t\tfree(e->right.expr);\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\t*e = *(e->left.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t} else if (e->right.expr->left.sym == &symbol_yes) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_yes;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn e;\n}\n\n/*\n * bool FOO!=n => FOO\n */\nstruct expr *expr_trans_bool(struct expr *e)\n{\n\tif (!e)\n\t\treturn NULL;\n\tswitch (e->type) {\n\tcase E_AND:\n\tcase E_OR:\n\tcase E_NOT:\n\t\te->left.expr = expr_trans_bool(e->left.expr);\n\t\te->right.expr = expr_trans_bool(e->right.expr);\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\t// FOO!=n -> FOO\n\t\tif (e->left.sym->type == S_TRISTATE) {\n\t\t\tif (e->right.sym == &symbol_no) {\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->right.sym = NULL;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn e;\n}\n\n/*\n * e1 || e2 -> ?\n */\nstatic struct expr *expr_join_or(struct expr *e1, struct expr *e2)\n{\n\tstruct expr *tmp;\n\tstruct symbol *sym1, *sym2;\n\n\tif (expr_eq(e1, e2))\n\t\treturn expr_copy(e1);\n\tif (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)\n\t\treturn NULL;\n\tif (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)\n\t\treturn NULL;\n\tif (e1->type == E_NOT) {\n\t\ttmp = e1->left.expr;\n\t\tif (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym1 = tmp->left.sym;\n\t} else\n\t\tsym1 = e1->left.sym;\n\tif (e2->type == E_NOT) {\n\t\tif (e2->left.expr->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym2 = e2->left.expr->left.sym;\n\t} else\n\t\tsym2 = e2->left.sym;\n\tif (sym1 != sym2)\n\t\treturn NULL;\n\tif (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)\n\t\treturn NULL;\n\tif (sym1->type == S_TRISTATE) {\n\t\tif (e1->type == E_EQUAL && e2->type == E_EQUAL &&\n\t\t    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||\n\t\t     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {\n\t\t\t// (a='y') || (a='m') -> (a!='n')\n\t\t\treturn expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);\n\t\t}\n\t\tif (e1->type == E_EQUAL && e2->type == E_EQUAL &&\n\t\t    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||\n\t\t     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {\n\t\t\t// (a='y') || (a='n') -> (a!='m')\n\t\t\treturn expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);\n\t\t}\n\t\tif (e1->type == E_EQUAL && e2->type == E_EQUAL &&\n\t\t    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||\n\t\t     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {\n\t\t\t// (a='m') || (a='n') -> (a!='y')\n\t\t\treturn expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);\n\t\t}\n\t}\n\tif (sym1->type == S_BOOLEAN && sym1 == sym2) {\n\t\tif ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||\n\t\t    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))\n\t\t\treturn expr_alloc_symbol(&symbol_yes);\n\t}\n\n\tif (DEBUG_EXPR) {\n\t\tprintf(\"optimize (\");\n\t\texpr_fprint(e1, stdout);\n\t\tprintf(\") || (\");\n\t\texpr_fprint(e2, stdout);\n\t\tprintf(\")?\\n\");\n\t}\n\treturn NULL;\n}\n\nstatic struct expr *expr_join_and(struct expr *e1, struct expr *e2)\n{\n\tstruct expr *tmp;\n\tstruct symbol *sym1, *sym2;\n\n\tif (expr_eq(e1, e2))\n\t\treturn expr_copy(e1);\n\tif (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)\n\t\treturn NULL;\n\tif (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)\n\t\treturn NULL;\n\tif (e1->type == E_NOT) {\n\t\ttmp = e1->left.expr;\n\t\tif (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym1 = tmp->left.sym;\n\t} else\n\t\tsym1 = e1->left.sym;\n\tif (e2->type == E_NOT) {\n\t\tif (e2->left.expr->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym2 = e2->left.expr->left.sym;\n\t} else\n\t\tsym2 = e2->left.sym;\n\tif (sym1 != sym2)\n\t\treturn NULL;\n\tif (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)\n\t\treturn NULL;\n\n\tif ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||\n\t    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))\n\t\t// (a) && (a='y') -> (a='y')\n\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);\n\n\tif ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||\n\t    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))\n\t\t// (a) && (a!='n') -> (a)\n\t\treturn expr_alloc_symbol(sym1);\n\n\tif ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||\n\t    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))\n\t\t// (a) && (a!='m') -> (a='y')\n\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);\n\n\tif (sym1->type == S_TRISTATE) {\n\t\tif (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {\n\t\t\t// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'\n\t\t\tsym2 = e1->right.sym;\n\t\t\tif ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))\n\t\t\t\treturn sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)\n\t\t\t\t\t\t\t     : expr_alloc_symbol(&symbol_no);\n\t\t}\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {\n\t\t\t// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'\n\t\t\tsym2 = e2->right.sym;\n\t\t\tif ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))\n\t\t\t\treturn sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)\n\t\t\t\t\t\t\t     : expr_alloc_symbol(&symbol_no);\n\t\t}\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&\n\t\t\t   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||\n\t\t\t    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))\n\t\t\t// (a!='y') && (a!='n') -> (a='m')\n\t\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);\n\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&\n\t\t\t   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||\n\t\t\t    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))\n\t\t\t// (a!='y') && (a!='m') -> (a='n')\n\t\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_no);\n\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&\n\t\t\t   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||\n\t\t\t    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))\n\t\t\t// (a!='m') && (a!='n') -> (a='m')\n\t\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);\n\n\t\tif ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||\n\t\t    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||\n\t\t    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||\n\t\t    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))\n\t\t\treturn NULL;\n\t}\n\n\tif (DEBUG_EXPR) {\n\t\tprintf(\"optimize (\");\n\t\texpr_fprint(e1, stdout);\n\t\tprintf(\") && (\");\n\t\texpr_fprint(e2, stdout);\n\t\tprintf(\")?\\n\");\n\t}\n\treturn NULL;\n}\n\nstatic void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)\n{\n#define e1 (*ep1)\n#define e2 (*ep2)\n\tstruct expr *tmp;\n\n\tif (e1->type == type) {\n\t\texpr_eliminate_dups1(type, &e1->left.expr, &e2);\n\t\texpr_eliminate_dups1(type, &e1->right.expr, &e2);\n\t\treturn;\n\t}\n\tif (e2->type == type) {\n\t\texpr_eliminate_dups1(type, &e1, &e2->left.expr);\n\t\texpr_eliminate_dups1(type, &e1, &e2->right.expr);\n\t\treturn;\n\t}\n\tif (e1 == e2)\n\t\treturn;\n\n\tswitch (e1->type) {\n\tcase E_OR: case E_AND:\n\t\texpr_eliminate_dups1(e1->type, &e1, &e1);\n\tdefault:\n\t\t;\n\t}\n\n\tswitch (type) {\n\tcase E_OR:\n\t\ttmp = expr_join_or(e1, e2);\n\t\tif (tmp) {\n\t\t\texpr_free(e1); expr_free(e2);\n\t\t\te1 = expr_alloc_symbol(&symbol_no);\n\t\t\te2 = tmp;\n\t\t\ttrans_count++;\n\t\t}\n\t\tbreak;\n\tcase E_AND:\n\t\ttmp = expr_join_and(e1, e2);\n\t\tif (tmp) {\n\t\t\texpr_free(e1); expr_free(e2);\n\t\t\te1 = expr_alloc_symbol(&symbol_yes);\n\t\t\te2 = tmp;\n\t\t\ttrans_count++;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n#undef e1\n#undef e2\n}\n\nstatic void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)\n{\n#define e1 (*ep1)\n#define e2 (*ep2)\n\tstruct expr *tmp, *tmp1, *tmp2;\n\n\tif (e1->type == type) {\n\t\texpr_eliminate_dups2(type, &e1->left.expr, &e2);\n\t\texpr_eliminate_dups2(type, &e1->right.expr, &e2);\n\t\treturn;\n\t}\n\tif (e2->type == type) {\n\t\texpr_eliminate_dups2(type, &e1, &e2->left.expr);\n\t\texpr_eliminate_dups2(type, &e1, &e2->right.expr);\n\t}\n\tif (e1 == e2)\n\t\treturn;\n\n\tswitch (e1->type) {\n\tcase E_OR:\n\t\texpr_eliminate_dups2(e1->type, &e1, &e1);\n\t\t// (FOO || BAR) && (!FOO && !BAR) -> n\n\t\ttmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));\n\t\ttmp2 = expr_copy(e2);\n\t\ttmp = expr_extract_eq_and(&tmp1, &tmp2);\n\t\tif (expr_is_yes(tmp1)) {\n\t\t\texpr_free(e1);\n\t\t\te1 = expr_alloc_symbol(&symbol_no);\n\t\t\ttrans_count++;\n\t\t}\n\t\texpr_free(tmp2);\n\t\texpr_free(tmp1);\n\t\texpr_free(tmp);\n\t\tbreak;\n\tcase E_AND:\n\t\texpr_eliminate_dups2(e1->type, &e1, &e1);\n\t\t// (FOO && BAR) || (!FOO || !BAR) -> y\n\t\ttmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));\n\t\ttmp2 = expr_copy(e2);\n\t\ttmp = expr_extract_eq_or(&tmp1, &tmp2);\n\t\tif (expr_is_no(tmp1)) {\n\t\t\texpr_free(e1);\n\t\t\te1 = expr_alloc_symbol(&symbol_yes);\n\t\t\ttrans_count++;\n\t\t}\n\t\texpr_free(tmp2);\n\t\texpr_free(tmp1);\n\t\texpr_free(tmp);\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n#undef e1\n#undef e2\n}\n\nstruct expr *expr_eliminate_dups(struct expr *e)\n{\n\tint oldcount;\n\tif (!e)\n\t\treturn e;\n\n\toldcount = trans_count;\n\twhile (1) {\n\t\ttrans_count = 0;\n\t\tswitch (e->type) {\n\t\tcase E_OR: case E_AND:\n\t\t\texpr_eliminate_dups1(e->type, &e, &e);\n\t\t\texpr_eliminate_dups2(e->type, &e, &e);\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t\tif (!trans_count)\n\t\t\tbreak;\n\t\te = expr_eliminate_yn(e);\n\t}\n\ttrans_count = oldcount;\n\treturn e;\n}\n\nstruct expr *expr_transform(struct expr *e)\n{\n\tstruct expr *tmp;\n\n\tif (!e)\n\t\treturn NULL;\n\tswitch (e->type) {\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\tcase E_SYMBOL:\n\tcase E_LIST:\n\t\tbreak;\n\tdefault:\n\t\te->left.expr = expr_transform(e->left.expr);\n\t\te->right.expr = expr_transform(e->right.expr);\n\t}\n\n\tswitch (e->type) {\n\tcase E_EQUAL:\n\t\tif (e->left.sym->type != S_BOOLEAN)\n\t\t\tbreak;\n\t\tif (e->right.sym == &symbol_no) {\n\t\t\te->type = E_NOT;\n\t\t\te->left.expr = expr_alloc_symbol(e->left.sym);\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_mod) {\n\t\t\tprintf(\"boolean symbol %s tested for 'm'? test forced to 'n'\\n\", e->left.sym->name);\n\t\t\te->type = E_SYMBOL;\n\t\t\te->left.sym = &symbol_no;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_yes) {\n\t\t\te->type = E_SYMBOL;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\tif (e->left.sym->type != S_BOOLEAN)\n\t\t\tbreak;\n\t\tif (e->right.sym == &symbol_no) {\n\t\t\te->type = E_SYMBOL;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_mod) {\n\t\t\tprintf(\"boolean symbol %s tested for 'm'? test forced to 'y'\\n\", e->left.sym->name);\n\t\t\te->type = E_SYMBOL;\n\t\t\te->left.sym = &symbol_yes;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_yes) {\n\t\t\te->type = E_NOT;\n\t\t\te->left.expr = expr_alloc_symbol(e->left.sym);\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase E_NOT:\n\t\tswitch (e->left.expr->type) {\n\t\tcase E_NOT:\n\t\t\t// !!a -> a\n\t\t\ttmp = e->left.expr->left.expr;\n\t\t\tfree(e->left.expr);\n\t\t\tfree(e);\n\t\t\te = tmp;\n\t\t\te = expr_transform(e);\n\t\t\tbreak;\n\t\tcase E_EQUAL:\n\t\tcase E_UNEQUAL:\n\t\t\t// !a='x' -> a!='x'\n\t\t\ttmp = e->left.expr;\n\t\t\tfree(e);\n\t\t\te = tmp;\n\t\t\te->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;\n\t\t\tbreak;\n\t\tcase E_OR:\n\t\t\t// !(a || b) -> !a && !b\n\t\t\ttmp = e->left.expr;\n\t\t\te->type = E_AND;\n\t\t\te->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);\n\t\t\ttmp->type = E_NOT;\n\t\t\ttmp->right.expr = NULL;\n\t\t\te = expr_transform(e);\n\t\t\tbreak;\n\t\tcase E_AND:\n\t\t\t// !(a && b) -> !a || !b\n\t\t\ttmp = e->left.expr;\n\t\t\te->type = E_OR;\n\t\t\te->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);\n\t\t\ttmp->type = E_NOT;\n\t\t\ttmp->right.expr = NULL;\n\t\t\te = expr_transform(e);\n\t\t\tbreak;\n\t\tcase E_SYMBOL:\n\t\t\tif (e->left.expr->left.sym == &symbol_yes) {\n\t\t\t\t// !'y' -> 'n'\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\tfree(e);\n\t\t\t\te = tmp;\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_no;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (e->left.expr->left.sym == &symbol_mod) {\n\t\t\t\t// !'m' -> 'm'\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\tfree(e);\n\t\t\t\te = tmp;\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_mod;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (e->left.expr->left.sym == &symbol_no) {\n\t\t\t\t// !'n' -> 'y'\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\tfree(e);\n\t\t\t\te = tmp;\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_yes;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn e;\n}\n\nint expr_contains_symbol(struct expr *dep, struct symbol *sym)\n{\n\tif (!dep)\n\t\treturn 0;\n\n\tswitch (dep->type) {\n\tcase E_AND:\n\tcase E_OR:\n\t\treturn expr_contains_symbol(dep->left.expr, sym) ||\n\t\t       expr_contains_symbol(dep->right.expr, sym);\n\tcase E_SYMBOL:\n\t\treturn dep->left.sym == sym;\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\t\treturn dep->left.sym == sym ||\n\t\t       dep->right.sym == sym;\n\tcase E_NOT:\n\t\treturn expr_contains_symbol(dep->left.expr, sym);\n\tdefault:\n\t\t;\n\t}\n\treturn 0;\n}\n\nbool expr_depends_symbol(struct expr *dep, struct symbol *sym)\n{\n\tif (!dep)\n\t\treturn false;\n\n\tswitch (dep->type) {\n\tcase E_AND:\n\t\treturn expr_depends_symbol(dep->left.expr, sym) ||\n\t\t       expr_depends_symbol(dep->right.expr, sym);\n\tcase E_SYMBOL:\n\t\treturn dep->left.sym == sym;\n\tcase E_EQUAL:\n\t\tif (dep->left.sym == sym) {\n\t\t\tif (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)\n\t\t\t\treturn true;\n\t\t}\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\tif (dep->left.sym == sym) {\n\t\t\tif (dep->right.sym == &symbol_no)\n\t\t\t\treturn true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n \treturn false;\n}\n\nstruct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)\n{\n\tstruct expr *tmp = NULL;\n\texpr_extract_eq(E_AND, &tmp, ep1, ep2);\n\tif (tmp) {\n\t\t*ep1 = expr_eliminate_yn(*ep1);\n\t\t*ep2 = expr_eliminate_yn(*ep2);\n\t}\n\treturn tmp;\n}\n\nstruct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)\n{\n\tstruct expr *tmp = NULL;\n\texpr_extract_eq(E_OR, &tmp, ep1, ep2);\n\tif (tmp) {\n\t\t*ep1 = expr_eliminate_yn(*ep1);\n\t\t*ep2 = expr_eliminate_yn(*ep2);\n\t}\n\treturn tmp;\n}\n\nvoid expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)\n{\n#define e1 (*ep1)\n#define e2 (*ep2)\n\tif (e1->type == type) {\n\t\texpr_extract_eq(type, ep, &e1->left.expr, &e2);\n\t\texpr_extract_eq(type, ep, &e1->right.expr, &e2);\n\t\treturn;\n\t}\n\tif (e2->type == type) {\n\t\texpr_extract_eq(type, ep, ep1, &e2->left.expr);\n\t\texpr_extract_eq(type, ep, ep1, &e2->right.expr);\n\t\treturn;\n\t}\n\tif (expr_eq(e1, e2)) {\n\t\t*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;\n\t\texpr_free(e2);\n\t\tif (type == E_AND) {\n\t\t\te1 = expr_alloc_symbol(&symbol_yes);\n\t\t\te2 = expr_alloc_symbol(&symbol_yes);\n\t\t} else if (type == E_OR) {\n\t\t\te1 = expr_alloc_symbol(&symbol_no);\n\t\t\te2 = expr_alloc_symbol(&symbol_no);\n\t\t}\n\t}\n#undef e1\n#undef e2\n}\n\nstruct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)\n{\n\tstruct expr *e1, *e2;\n\n\tif (!e) {\n\t\te = expr_alloc_symbol(sym);\n\t\tif (type == E_UNEQUAL)\n\t\t\te = expr_alloc_one(E_NOT, e);\n\t\treturn e;\n\t}\n\tswitch (e->type) {\n\tcase E_AND:\n\t\te1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);\n\t\te2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);\n\t\tif (sym == &symbol_yes)\n\t\t\te = expr_alloc_two(E_AND, e1, e2);\n\t\tif (sym == &symbol_no)\n\t\t\te = expr_alloc_two(E_OR, e1, e2);\n\t\tif (type == E_UNEQUAL)\n\t\t\te = expr_alloc_one(E_NOT, e);\n\t\treturn e;\n\tcase E_OR:\n\t\te1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);\n\t\te2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);\n\t\tif (sym == &symbol_yes)\n\t\t\te = expr_alloc_two(E_OR, e1, e2);\n\t\tif (sym == &symbol_no)\n\t\t\te = expr_alloc_two(E_AND, e1, e2);\n\t\tif (type == E_UNEQUAL)\n\t\t\te = expr_alloc_one(E_NOT, e);\n\t\treturn e;\n\tcase E_NOT:\n\t\treturn expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);\n\tcase E_UNEQUAL:\n\tcase E_EQUAL:\n\t\tif (type == E_EQUAL) {\n\t\t\tif (sym == &symbol_yes)\n\t\t\t\treturn expr_copy(e);\n\t\t\tif (sym == &symbol_mod)\n\t\t\t\treturn expr_alloc_symbol(&symbol_no);\n\t\t\tif (sym == &symbol_no)\n\t\t\t\treturn expr_alloc_one(E_NOT, expr_copy(e));\n\t\t} else {\n\t\t\tif (sym == &symbol_yes)\n\t\t\t\treturn expr_alloc_one(E_NOT, expr_copy(e));\n\t\t\tif (sym == &symbol_mod)\n\t\t\t\treturn expr_alloc_symbol(&symbol_yes);\n\t\t\tif (sym == &symbol_no)\n\t\t\t\treturn expr_copy(e);\n\t\t}\n\t\tbreak;\n\tcase E_SYMBOL:\n\t\treturn expr_alloc_comp(type, e->left.sym, sym);\n\tcase E_LIST:\n\tcase E_RANGE:\n\tcase E_NONE:\n\t\t/* panic */;\n\t}\n\treturn NULL;\n}\n\ntristate expr_calc_value(struct expr *e)\n{\n\ttristate val1, val2;\n\tconst char *str1, *str2;\n\n\tif (!e)\n\t\treturn yes;\n\n\tswitch (e->type) {\n\tcase E_SYMBOL:\n\t\tsym_calc_value(e->left.sym);\n\t\treturn e->left.sym->curr.tri;\n\tcase E_AND:\n\t\tval1 = expr_calc_value(e->left.expr);\n\t\tval2 = expr_calc_value(e->right.expr);\n\t\treturn EXPR_AND(val1, val2);\n\tcase E_OR:\n\t\tval1 = expr_calc_value(e->left.expr);\n\t\tval2 = expr_calc_value(e->right.expr);\n\t\treturn EXPR_OR(val1, val2);\n\tcase E_NOT:\n\t\tval1 = expr_calc_value(e->left.expr);\n\t\treturn EXPR_NOT(val1);\n\tcase E_EQUAL:\n\t\tsym_calc_value(e->left.sym);\n\t\tsym_calc_value(e->right.sym);\n\t\tstr1 = sym_get_string_value(e->left.sym);\n\t\tstr2 = sym_get_string_value(e->right.sym);\n\t\treturn !strcmp(str1, str2) ? yes : no;\n\tcase E_UNEQUAL:\n\t\tsym_calc_value(e->left.sym);\n\t\tsym_calc_value(e->right.sym);\n\t\tstr1 = sym_get_string_value(e->left.sym);\n\t\tstr2 = sym_get_string_value(e->right.sym);\n\t\treturn !strcmp(str1, str2) ? no : yes;\n\tdefault:\n\t\tprintf(\"expr_calc_value: %d?\\n\", e->type);\n\t\treturn no;\n\t}\n}\n\nint expr_compare_type(enum expr_type t1, enum expr_type t2)\n{\n#if 0\n\treturn 1;\n#else\n\tif (t1 == t2)\n\t\treturn 0;\n\tswitch (t1) {\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\t\tif (t2 == E_NOT)\n\t\t\treturn 1;\n\tcase E_NOT:\n\t\tif (t2 == E_AND)\n\t\t\treturn 1;\n\tcase E_AND:\n\t\tif (t2 == E_OR)\n\t\t\treturn 1;\n\tcase E_OR:\n\t\tif (t2 == E_LIST)\n\t\t\treturn 1;\n\tcase E_LIST:\n\t\tif (t2 == 0)\n\t\t\treturn 1;\n\tdefault:\n\t\treturn -1;\n\t}\n\tprintf(\"[%dgt%d?]\", t1, t2);\n\treturn 0;\n#endif\n}\n\nstatic inline struct expr *\nexpr_get_leftmost_symbol(const struct expr *e)\n{\n\n\tif (e == NULL)\n\t\treturn NULL;\n\n\twhile (e->type != E_SYMBOL)\n\t\te = e->left.expr;\n\n\treturn expr_copy(e);\n}\n\n/*\n * Given expression `e1' and `e2', returns the leaf of the longest\n * sub-expression of `e1' not containing 'e2.\n */\nstruct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)\n{\n\tstruct expr *ret;\n\n\tswitch (e1->type) {\n\tcase E_OR:\n\t\treturn expr_alloc_and(\n\t\t    expr_simplify_unmet_dep(e1->left.expr, e2),\n\t\t    expr_simplify_unmet_dep(e1->right.expr, e2));\n\tcase E_AND: {\n\t\tstruct expr *e;\n\t\te = expr_alloc_and(expr_copy(e1), expr_copy(e2));\n\t\te = expr_eliminate_dups(e);\n\t\tret = (!expr_eq(e, e1)) ? e1 : NULL;\n\t\texpr_free(e);\n\t\tbreak;\n\t\t}\n\tdefault:\n\t\tret = e1;\n\t\tbreak;\n\t}\n\n\treturn expr_get_leftmost_symbol(ret);\n}\n\nvoid expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)\n{\n\tif (!e) {\n\t\tfn(data, NULL, \"y\");\n\t\treturn;\n\t}\n\n\tif (expr_compare_type(prevtoken, e->type) > 0)\n\t\tfn(data, NULL, \"(\");\n\tswitch (e->type) {\n\tcase E_SYMBOL:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tbreak;\n\tcase E_NOT:\n\t\tfn(data, NULL, \"!\");\n\t\texpr_print(e->left.expr, fn, data, E_NOT);\n\t\tbreak;\n\tcase E_EQUAL:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tfn(data, NULL, \"=\");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tfn(data, NULL, \"!=\");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tbreak;\n\tcase E_OR:\n\t\texpr_print(e->left.expr, fn, data, E_OR);\n\t\tfn(data, NULL, \" || \");\n\t\texpr_print(e->right.expr, fn, data, E_OR);\n\t\tbreak;\n\tcase E_AND:\n\t\texpr_print(e->left.expr, fn, data, E_AND);\n\t\tfn(data, NULL, \" && \");\n\t\texpr_print(e->right.expr, fn, data, E_AND);\n\t\tbreak;\n\tcase E_LIST:\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tif (e->left.expr) {\n\t\t\tfn(data, NULL, \" ^ \");\n\t\t\texpr_print(e->left.expr, fn, data, E_LIST);\n\t\t}\n\t\tbreak;\n\tcase E_RANGE:\n\t\tfn(data, NULL, \"[\");\n\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\tfn(data, NULL, \" \");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tfn(data, NULL, \"]\");\n\t\tbreak;\n\tdefault:\n\t  {\n\t\tchar buf[32];\n\t\tsprintf(buf, \"<unknown type %d>\", e->type);\n\t\tfn(data, NULL, buf);\n\t\tbreak;\n\t  }\n\t}\n\tif (expr_compare_type(prevtoken, e->type) > 0)\n\t\tfn(data, NULL, \")\");\n}\n\nstatic void expr_print_file_helper(void *data, struct symbol *sym, const char *str)\n{\n\txfwrite(str, strlen(str), 1, data);\n}\n\nvoid expr_fprint(struct expr *e, FILE *out)\n{\n\texpr_print(e, expr_print_file_helper, out, E_NONE);\n}\n\nstatic void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)\n{\n\tstruct gstr *gs = (struct gstr*)data;\n\tconst char *sym_str = NULL;\n\n\tif (sym)\n\t\tsym_str = sym_get_string_value(sym);\n\n\tif (gs->max_width) {\n\t\tunsigned extra_length = strlen(str);\n\t\tconst char *last_cr = strrchr(gs->s, '\\n');\n\t\tunsigned last_line_length;\n\n\t\tif (sym_str)\n\t\t\textra_length += 4 + strlen(sym_str);\n\n\t\tif (!last_cr)\n\t\t\tlast_cr = gs->s;\n\n\t\tlast_line_length = strlen(gs->s) - (last_cr - gs->s);\n\n\t\tif ((last_line_length + extra_length) > gs->max_width)\n\t\t\tstr_append(gs, \"\\\\\\n\");\n\t}\n\n\tstr_append(gs, str);\n\tif (sym && sym->type != S_UNKNOWN)\n\t\tstr_printf(gs, \" [=%s]\", sym_str);\n}\n\nvoid expr_gstr_print(struct expr *e, struct gstr *gs)\n{\n\texpr_print(e, expr_print_gstr_helper, gs, E_NONE);\n}\n"
  },
  {
    "path": "kconfig/expr.h",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#ifndef EXPR_H\n#define EXPR_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <assert.h>\n#include <stdio.h>\n#include \"list.h\"\n#ifndef __cplusplus\n#include <stdbool.h>\n#endif\n\nstruct file {\n\tstruct file *next;\n\tstruct file *parent;\n\tconst char *name;\n\tint lineno;\n};\n\ntypedef enum tristate {\n\tno, mod, yes\n} tristate;\n\nenum expr_type {\n\tE_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE\n};\n\nunion expr_data {\n\tstruct expr *expr;\n\tstruct symbol *sym;\n};\n\nstruct expr {\n\tenum expr_type type;\n\tunion expr_data left, right;\n};\n\n#define EXPR_OR(dep1, dep2)\t(((dep1)>(dep2))?(dep1):(dep2))\n#define EXPR_AND(dep1, dep2)\t(((dep1)<(dep2))?(dep1):(dep2))\n#define EXPR_NOT(dep)\t\t(2-(dep))\n\n#define expr_list_for_each_sym(l, e, s) \\\n\tfor (e = (l); e && (s = e->right.sym); e = e->left.expr)\n\nstruct expr_value {\n\tstruct expr *expr;\n\ttristate tri;\n};\n\nstruct symbol_value {\n\tvoid *val;\n\ttristate tri;\n};\n\nenum symbol_type {\n\tS_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER\n};\n\n/* enum values are used as index to symbol.def[] */\nenum {\n\tS_DEF_USER,\t\t/* main user value */\n\tS_DEF_AUTO,\t\t/* values read from auto.conf */\n\tS_DEF_DEF3,\t\t/* Reserved for UI usage */\n\tS_DEF_DEF4,\t\t/* Reserved for UI usage */\n\tS_DEF_COUNT\n};\n\nstruct symbol {\n\tstruct symbol *next;\n\tchar *name;\n\tenum symbol_type type;\n\tstruct symbol_value curr;\n\tstruct symbol_value def[S_DEF_COUNT];\n\ttristate visible;\n\tint flags;\n\tstruct property *prop;\n\tstruct expr_value dir_dep;\n\tstruct expr_value rev_dep;\n};\n\n#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)\n\n#define SYMBOL_CONST      0x0001  /* symbol is const */\n#define SYMBOL_CHECK      0x0008  /* used during dependency checking */\n#define SYMBOL_CHOICE     0x0010  /* start of a choice block (null name) */\n#define SYMBOL_CHOICEVAL  0x0020  /* used as a value in a choice block */\n#define SYMBOL_VALID      0x0080  /* set when symbol.curr is calculated */\n#define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */\n#define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */\n#define SYMBOL_CHANGED    0x0400  /* ? */\n#define SYMBOL_AUTO       0x1000  /* value from environment variable */\n#define SYMBOL_CHECKED    0x2000  /* used during dependency checking */\n#define SYMBOL_WARNED     0x8000  /* warning has been issued */\n\n/* Set when symbol.def[] is used */\n#define SYMBOL_DEF        0x10000  /* First bit of SYMBOL_DEF */\n#define SYMBOL_DEF_USER   0x10000  /* symbol.def[S_DEF_USER] is valid */\n#define SYMBOL_DEF_AUTO   0x20000  /* symbol.def[S_DEF_AUTO] is valid */\n#define SYMBOL_DEF3       0x40000  /* symbol.def[S_DEF_3] is valid */\n#define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */\n\n/* choice values need to be set before calculating this symbol value */\n#define SYMBOL_NEED_SET_CHOICE_VALUES  0x100000\n\n/* Set symbol to y if allnoconfig; used for symbols that hide others */\n#define SYMBOL_ALLNOCONFIG_Y 0x200000\n\n#define SYMBOL_MAXLENGTH\t256\n#define SYMBOL_HASHSIZE\t\t9973\n\n/* A property represent the config options that can be associated\n * with a config \"symbol\".\n * Sample:\n * config FOO\n *         default y\n *         prompt \"foo prompt\"\n *         select BAR\n * config BAZ\n *         int \"BAZ Value\"\n *         range 1..255\n */\nenum prop_type {\n\tP_UNKNOWN,\n\tP_PROMPT,   /* prompt \"foo prompt\" or \"BAZ Value\" */\n\tP_COMMENT,  /* text associated with a comment */\n\tP_MENU,     /* prompt associated with a menuconfig option */\n\tP_DEFAULT,  /* default y */\n\tP_CHOICE,   /* choice value */\n\tP_SELECT,   /* select BAR */\n\tP_RANGE,    /* range 7..100 (for a symbol) */\n\tP_ENV,      /* value from environment variable */\n\tP_SYMBOL,   /* where a symbol is defined */\n};\n\nstruct property {\n\tstruct property *next;     /* next property - null if last */\n\tstruct symbol *sym;        /* the symbol for which the property is associated */\n\tenum prop_type type;       /* type of property */\n\tconst char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */\n\tstruct expr_value visible;\n\tstruct expr *expr;         /* the optional conditional part of the property */\n\tstruct menu *menu;         /* the menu the property are associated with\n\t                            * valid for: P_SELECT, P_RANGE, P_CHOICE,\n\t                            * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */\n\tstruct file *file;         /* what file was this property defined */\n\tint lineno;                /* what lineno was this property defined */\n};\n\n#define for_all_properties(sym, st, tok) \\\n\tfor (st = sym->prop; st; st = st->next) \\\n\t\tif (st->type == (tok))\n#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)\n#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)\n#define for_all_prompts(sym, st) \\\n\tfor (st = sym->prop; st; st = st->next) \\\n\t\tif (st->text)\n\nstruct menu {\n\tstruct menu *next;\n\tstruct menu *parent;\n\tstruct menu *list;\n\tstruct symbol *sym;\n\tstruct property *prompt;\n\tstruct expr *visibility;\n\tstruct expr *dep;\n\tunsigned int flags;\n\tchar *help;\n\tstruct file *file;\n\tint lineno;\n\tvoid *data;\n};\n\n#define MENU_CHANGED\t\t0x0001\n#define MENU_ROOT\t\t0x0002\n\nstruct jump_key {\n\tstruct list_head entries;\n\tsize_t offset;\n\tstruct menu *target;\n\tint index;\n};\n\n#define JUMP_NB\t\t\t9\n\nextern struct file *file_list;\nextern struct file *current_file;\nstruct file *lookup_file(const char *name);\n\nextern struct symbol symbol_yes, symbol_no, symbol_mod;\nextern struct symbol *modules_sym;\nextern struct symbol *sym_defconfig_list;\nextern int cdebug;\nstruct expr *expr_alloc_symbol(struct symbol *sym);\nstruct expr *expr_alloc_one(enum expr_type type, struct expr *ce);\nstruct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);\nstruct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);\nstruct expr *expr_alloc_and(struct expr *e1, struct expr *e2);\nstruct expr *expr_alloc_or(struct expr *e1, struct expr *e2);\nstruct expr *expr_copy(const struct expr *org);\nvoid expr_free(struct expr *e);\nint expr_eq(struct expr *e1, struct expr *e2);\nvoid expr_eliminate_eq(struct expr **ep1, struct expr **ep2);\ntristate expr_calc_value(struct expr *e);\nstruct expr *expr_eliminate_yn(struct expr *e);\nstruct expr *expr_trans_bool(struct expr *e);\nstruct expr *expr_eliminate_dups(struct expr *e);\nstruct expr *expr_transform(struct expr *e);\nint expr_contains_symbol(struct expr *dep, struct symbol *sym);\nbool expr_depends_symbol(struct expr *dep, struct symbol *sym);\nstruct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);\nstruct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);\nvoid expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);\nstruct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);\nstruct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);\n\nvoid expr_fprint(struct expr *e, FILE *out);\nstruct gstr; /* forward */\nvoid expr_gstr_print(struct expr *e, struct gstr *gs);\n\nstatic inline int expr_is_yes(struct expr *e)\n{\n\treturn !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);\n}\n\nstatic inline int expr_is_no(struct expr *e)\n{\n\treturn e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* EXPR_H */\n"
  },
  {
    "path": "kconfig/frosted.conf",
    "content": ""
  },
  {
    "path": "kconfig/gconf.c",
    "content": "/* Hey EMACS -*- linux-c -*- */\n/*\n *\n * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info>\n * Released under the terms of the GNU GPL v2.0.\n *\n */\n\n#ifdef HAVE_CONFIG_H\n#  include <config.h>\n#endif\n\n#include <stdlib.h>\n#include \"lkc.h\"\n#include \"images.c\"\n\n#include <glade/glade.h>\n#include <gtk/gtk.h>\n#include <glib.h>\n#include <gdk/gdkkeysyms.h>\n\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <time.h>\n\n//#define DEBUG\n\nenum {\n\tSINGLE_VIEW, SPLIT_VIEW, FULL_VIEW\n};\n\nenum {\n\tOPT_NORMAL, OPT_ALL, OPT_PROMPT\n};\n\nstatic gint view_mode = FULL_VIEW;\nstatic gboolean show_name = TRUE;\nstatic gboolean show_range = TRUE;\nstatic gboolean show_value = TRUE;\nstatic gboolean resizeable = FALSE;\nstatic int opt_mode = OPT_NORMAL;\n\nGtkWidget *main_wnd = NULL;\nGtkWidget *tree1_w = NULL;\t// left  frame\nGtkWidget *tree2_w = NULL;\t// right frame\nGtkWidget *text_w = NULL;\nGtkWidget *hpaned = NULL;\nGtkWidget *vpaned = NULL;\nGtkWidget *back_btn = NULL;\nGtkWidget *save_btn = NULL;\nGtkWidget *save_menu_item = NULL;\n\nGtkTextTag *tag1, *tag2;\nGdkColor color;\n\nGtkTreeStore *tree1, *tree2, *tree;\nGtkTreeModel *model1, *model2;\nstatic GtkTreeIter *parents[256];\nstatic gint indent;\n\nstatic struct menu *current; // current node for SINGLE view\nstatic struct menu *browsed; // browsed node for SPLIT view\n\nenum {\n\tCOL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE,\n\tCOL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF,\n\tCOL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD,\n\tCOL_NUMBER\n};\n\nstatic void display_list(void);\nstatic void display_tree(struct menu *menu);\nstatic void display_tree_part(void);\nstatic void update_tree(struct menu *src, GtkTreeIter * dst);\nstatic void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);\nstatic gchar **fill_row(struct menu *menu);\nstatic void conf_changed(void);\n\n/* Helping/Debugging Functions */\n\nconst char *dbg_sym_flags(int val)\n{\n\tstatic char buf[256];\n\n\tbzero(buf, 256);\n\n\tif (val & SYMBOL_CONST)\n\t\tstrcat(buf, \"const/\");\n\tif (val & SYMBOL_CHECK)\n\t\tstrcat(buf, \"check/\");\n\tif (val & SYMBOL_CHOICE)\n\t\tstrcat(buf, \"choice/\");\n\tif (val & SYMBOL_CHOICEVAL)\n\t\tstrcat(buf, \"choiceval/\");\n\tif (val & SYMBOL_VALID)\n\t\tstrcat(buf, \"valid/\");\n\tif (val & SYMBOL_OPTIONAL)\n\t\tstrcat(buf, \"optional/\");\n\tif (val & SYMBOL_WRITE)\n\t\tstrcat(buf, \"write/\");\n\tif (val & SYMBOL_CHANGED)\n\t\tstrcat(buf, \"changed/\");\n\tif (val & SYMBOL_AUTO)\n\t\tstrcat(buf, \"auto/\");\n\n\tbuf[strlen(buf) - 1] = '\\0';\n\n\treturn buf;\n}\n\nvoid replace_button_icon(GladeXML * xml, GdkDrawable * window,\n\t\t\t GtkStyle * style, gchar * btn_name, gchar ** xpm)\n{\n\tGdkPixmap *pixmap;\n\tGdkBitmap *mask;\n\tGtkToolButton *button;\n\tGtkWidget *image;\n\n\tpixmap = gdk_pixmap_create_from_xpm_d(window, &mask,\n\t\t\t\t\t      &style->bg[GTK_STATE_NORMAL],\n\t\t\t\t\t      xpm);\n\n\tbutton = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name));\n\timage = gtk_image_new_from_pixmap(pixmap, mask);\n\tgtk_widget_show(image);\n\tgtk_tool_button_set_icon_widget(button, image);\n}\n\n/* Main Window Initialization */\nvoid init_main_window(const gchar * glade_file)\n{\n\tGladeXML *xml;\n\tGtkWidget *widget;\n\tGtkTextBuffer *txtbuf;\n\tGtkStyle *style;\n\n\txml = glade_xml_new(glade_file, \"window1\", NULL);\n\tif (!xml)\n\t\tg_error(_(\"GUI loading failed !\\n\"));\n\tglade_xml_signal_autoconnect(xml);\n\n\tmain_wnd = glade_xml_get_widget(xml, \"window1\");\n\thpaned = glade_xml_get_widget(xml, \"hpaned1\");\n\tvpaned = glade_xml_get_widget(xml, \"vpaned1\");\n\ttree1_w = glade_xml_get_widget(xml, \"treeview1\");\n\ttree2_w = glade_xml_get_widget(xml, \"treeview2\");\n\ttext_w = glade_xml_get_widget(xml, \"textview3\");\n\n\tback_btn = glade_xml_get_widget(xml, \"button1\");\n\tgtk_widget_set_sensitive(back_btn, FALSE);\n\n\twidget = glade_xml_get_widget(xml, \"show_name1\");\n\tgtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,\n\t\t\t\t       show_name);\n\n\twidget = glade_xml_get_widget(xml, \"show_range1\");\n\tgtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,\n\t\t\t\t       show_range);\n\n\twidget = glade_xml_get_widget(xml, \"show_data1\");\n\tgtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,\n\t\t\t\t       show_value);\n\n\tsave_btn = glade_xml_get_widget(xml, \"button3\");\n\tsave_menu_item = glade_xml_get_widget(xml, \"save1\");\n\tconf_set_changed_callback(conf_changed);\n\n\tstyle = gtk_widget_get_style(main_wnd);\n\twidget = glade_xml_get_widget(xml, \"toolbar1\");\n\n#if 0\t/* Use stock Gtk icons instead */\n\treplace_button_icon(xml, main_wnd->window, style,\n\t\t\t    \"button1\", (gchar **) xpm_back);\n\treplace_button_icon(xml, main_wnd->window, style,\n\t\t\t    \"button2\", (gchar **) xpm_load);\n\treplace_button_icon(xml, main_wnd->window, style,\n\t\t\t    \"button3\", (gchar **) xpm_save);\n#endif\n\treplace_button_icon(xml, main_wnd->window, style,\n\t\t\t    \"button4\", (gchar **) xpm_single_view);\n\treplace_button_icon(xml, main_wnd->window, style,\n\t\t\t    \"button5\", (gchar **) xpm_split_view);\n\treplace_button_icon(xml, main_wnd->window, style,\n\t\t\t    \"button6\", (gchar **) xpm_tree_view);\n\n#if 0\n\tswitch (view_mode) {\n\tcase SINGLE_VIEW:\n\t\twidget = glade_xml_get_widget(xml, \"button4\");\n\t\tg_signal_emit_by_name(widget, \"clicked\");\n\t\tbreak;\n\tcase SPLIT_VIEW:\n\t\twidget = glade_xml_get_widget(xml, \"button5\");\n\t\tg_signal_emit_by_name(widget, \"clicked\");\n\t\tbreak;\n\tcase FULL_VIEW:\n\t\twidget = glade_xml_get_widget(xml, \"button6\");\n\t\tg_signal_emit_by_name(widget, \"clicked\");\n\t\tbreak;\n\t}\n#endif\n\ttxtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));\n\ttag1 = gtk_text_buffer_create_tag(txtbuf, \"mytag1\",\n\t\t\t\t\t  \"foreground\", \"red\",\n\t\t\t\t\t  \"weight\", PANGO_WEIGHT_BOLD,\n\t\t\t\t\t  NULL);\n\ttag2 = gtk_text_buffer_create_tag(txtbuf, \"mytag2\",\n\t\t\t\t\t  /*\"style\", PANGO_STYLE_OBLIQUE, */\n\t\t\t\t\t  NULL);\n\n\tgtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);\n\n\tgtk_widget_show(main_wnd);\n}\n\nvoid init_tree_model(void)\n{\n\tgint i;\n\n\ttree = tree2 = gtk_tree_store_new(COL_NUMBER,\n\t\t\t\t\t  G_TYPE_STRING, G_TYPE_STRING,\n\t\t\t\t\t  G_TYPE_STRING, G_TYPE_STRING,\n\t\t\t\t\t  G_TYPE_STRING, G_TYPE_STRING,\n\t\t\t\t\t  G_TYPE_POINTER, GDK_TYPE_COLOR,\n\t\t\t\t\t  G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,\n\t\t\t\t\t  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,\n\t\t\t\t\t  G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,\n\t\t\t\t\t  G_TYPE_BOOLEAN);\n\tmodel2 = GTK_TREE_MODEL(tree2);\n\n\tfor (parents[0] = NULL, i = 1; i < 256; i++)\n\t\tparents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter));\n\n\ttree1 = gtk_tree_store_new(COL_NUMBER,\n\t\t\t\t   G_TYPE_STRING, G_TYPE_STRING,\n\t\t\t\t   G_TYPE_STRING, G_TYPE_STRING,\n\t\t\t\t   G_TYPE_STRING, G_TYPE_STRING,\n\t\t\t\t   G_TYPE_POINTER, GDK_TYPE_COLOR,\n\t\t\t\t   G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,\n\t\t\t\t   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,\n\t\t\t\t   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,\n\t\t\t\t   G_TYPE_BOOLEAN);\n\tmodel1 = GTK_TREE_MODEL(tree1);\n}\n\nvoid init_left_tree(void)\n{\n\tGtkTreeView *view = GTK_TREE_VIEW(tree1_w);\n\tGtkCellRenderer *renderer;\n\tGtkTreeSelection *sel;\n\tGtkTreeViewColumn *column;\n\n\tgtk_tree_view_set_model(view, model1);\n\tgtk_tree_view_set_headers_visible(view, TRUE);\n\tgtk_tree_view_set_rules_hint(view, TRUE);\n\n\tcolumn = gtk_tree_view_column_new();\n\tgtk_tree_view_append_column(view, column);\n\tgtk_tree_view_column_set_title(column, _(\"Options\"));\n\n\trenderer = gtk_cell_renderer_toggle_new();\n\tgtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\trenderer, FALSE);\n\tgtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\t    renderer,\n\t\t\t\t\t    \"active\", COL_BTNACT,\n\t\t\t\t\t    \"inconsistent\", COL_BTNINC,\n\t\t\t\t\t    \"visible\", COL_BTNVIS,\n\t\t\t\t\t    \"radio\", COL_BTNRAD, NULL);\n\trenderer = gtk_cell_renderer_text_new();\n\tgtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\trenderer, FALSE);\n\tgtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\t    renderer,\n\t\t\t\t\t    \"text\", COL_OPTION,\n\t\t\t\t\t    \"foreground-gdk\",\n\t\t\t\t\t    COL_COLOR, NULL);\n\n\tsel = gtk_tree_view_get_selection(view);\n\tgtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);\n\tgtk_widget_realize(tree1_w);\n}\n\nstatic void renderer_edited(GtkCellRendererText * cell,\n\t\t\t    const gchar * path_string,\n\t\t\t    const gchar * new_text, gpointer user_data);\n\nvoid init_right_tree(void)\n{\n\tGtkTreeView *view = GTK_TREE_VIEW(tree2_w);\n\tGtkCellRenderer *renderer;\n\tGtkTreeSelection *sel;\n\tGtkTreeViewColumn *column;\n\tgint i;\n\n\tgtk_tree_view_set_model(view, model2);\n\tgtk_tree_view_set_headers_visible(view, TRUE);\n\tgtk_tree_view_set_rules_hint(view, TRUE);\n\n\tcolumn = gtk_tree_view_column_new();\n\tgtk_tree_view_append_column(view, column);\n\tgtk_tree_view_column_set_title(column, _(\"Options\"));\n\n\trenderer = gtk_cell_renderer_pixbuf_new();\n\tgtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\trenderer, FALSE);\n\tgtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\t    renderer,\n\t\t\t\t\t    \"pixbuf\", COL_PIXBUF,\n\t\t\t\t\t    \"visible\", COL_PIXVIS, NULL);\n\trenderer = gtk_cell_renderer_toggle_new();\n\tgtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\trenderer, FALSE);\n\tgtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\t    renderer,\n\t\t\t\t\t    \"active\", COL_BTNACT,\n\t\t\t\t\t    \"inconsistent\", COL_BTNINC,\n\t\t\t\t\t    \"visible\", COL_BTNVIS,\n\t\t\t\t\t    \"radio\", COL_BTNRAD, NULL);\n\trenderer = gtk_cell_renderer_text_new();\n\tgtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\trenderer, FALSE);\n\tgtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column),\n\t\t\t\t\t    renderer,\n\t\t\t\t\t    \"text\", COL_OPTION,\n\t\t\t\t\t    \"foreground-gdk\",\n\t\t\t\t\t    COL_COLOR, NULL);\n\n\trenderer = gtk_cell_renderer_text_new();\n\tgtk_tree_view_insert_column_with_attributes(view, -1,\n\t\t\t\t\t\t    _(\"Name\"), renderer,\n\t\t\t\t\t\t    \"text\", COL_NAME,\n\t\t\t\t\t\t    \"foreground-gdk\",\n\t\t\t\t\t\t    COL_COLOR, NULL);\n\trenderer = gtk_cell_renderer_text_new();\n\tgtk_tree_view_insert_column_with_attributes(view, -1,\n\t\t\t\t\t\t    \"N\", renderer,\n\t\t\t\t\t\t    \"text\", COL_NO,\n\t\t\t\t\t\t    \"foreground-gdk\",\n\t\t\t\t\t\t    COL_COLOR, NULL);\n\trenderer = gtk_cell_renderer_text_new();\n\tgtk_tree_view_insert_column_with_attributes(view, -1,\n\t\t\t\t\t\t    \"M\", renderer,\n\t\t\t\t\t\t    \"text\", COL_MOD,\n\t\t\t\t\t\t    \"foreground-gdk\",\n\t\t\t\t\t\t    COL_COLOR, NULL);\n\trenderer = gtk_cell_renderer_text_new();\n\tgtk_tree_view_insert_column_with_attributes(view, -1,\n\t\t\t\t\t\t    \"Y\", renderer,\n\t\t\t\t\t\t    \"text\", COL_YES,\n\t\t\t\t\t\t    \"foreground-gdk\",\n\t\t\t\t\t\t    COL_COLOR, NULL);\n\trenderer = gtk_cell_renderer_text_new();\n\tgtk_tree_view_insert_column_with_attributes(view, -1,\n\t\t\t\t\t\t    _(\"Value\"), renderer,\n\t\t\t\t\t\t    \"text\", COL_VALUE,\n\t\t\t\t\t\t    \"editable\",\n\t\t\t\t\t\t    COL_EDIT,\n\t\t\t\t\t\t    \"foreground-gdk\",\n\t\t\t\t\t\t    COL_COLOR, NULL);\n\tg_signal_connect(G_OBJECT(renderer), \"edited\",\n\t\t\t G_CALLBACK(renderer_edited), NULL);\n\n\tcolumn = gtk_tree_view_get_column(view, COL_NAME);\n\tgtk_tree_view_column_set_visible(column, show_name);\n\tcolumn = gtk_tree_view_get_column(view, COL_NO);\n\tgtk_tree_view_column_set_visible(column, show_range);\n\tcolumn = gtk_tree_view_get_column(view, COL_MOD);\n\tgtk_tree_view_column_set_visible(column, show_range);\n\tcolumn = gtk_tree_view_get_column(view, COL_YES);\n\tgtk_tree_view_column_set_visible(column, show_range);\n\tcolumn = gtk_tree_view_get_column(view, COL_VALUE);\n\tgtk_tree_view_column_set_visible(column, show_value);\n\n\tif (resizeable) {\n\t\tfor (i = 0; i < COL_VALUE; i++) {\n\t\t\tcolumn = gtk_tree_view_get_column(view, i);\n\t\t\tgtk_tree_view_column_set_resizable(column, TRUE);\n\t\t}\n\t}\n\n\tsel = gtk_tree_view_get_selection(view);\n\tgtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);\n}\n\n\n/* Utility Functions */\n\n\nstatic void text_insert_help(struct menu *menu)\n{\n\tGtkTextBuffer *buffer;\n\tGtkTextIter start, end;\n\tconst char *prompt = _(menu_get_prompt(menu));\n\tstruct gstr help = str_new();\n\n\tmenu_get_ext_help(menu, &help);\n\n\tbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));\n\tgtk_text_buffer_get_bounds(buffer, &start, &end);\n\tgtk_text_buffer_delete(buffer, &start, &end);\n\tgtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);\n\n\tgtk_text_buffer_get_end_iter(buffer, &end);\n\tgtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1,\n\t\t\t\t\t NULL);\n\tgtk_text_buffer_insert_at_cursor(buffer, \"\\n\\n\", 2);\n\tgtk_text_buffer_get_end_iter(buffer, &end);\n\tgtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2,\n\t\t\t\t\t NULL);\n\tstr_free(&help);\n}\n\n\nstatic void text_insert_msg(const char *title, const char *message)\n{\n\tGtkTextBuffer *buffer;\n\tGtkTextIter start, end;\n\tconst char *msg = message;\n\n\tbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w));\n\tgtk_text_buffer_get_bounds(buffer, &start, &end);\n\tgtk_text_buffer_delete(buffer, &start, &end);\n\tgtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15);\n\n\tgtk_text_buffer_get_end_iter(buffer, &end);\n\tgtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1,\n\t\t\t\t\t NULL);\n\tgtk_text_buffer_insert_at_cursor(buffer, \"\\n\\n\", 2);\n\tgtk_text_buffer_get_end_iter(buffer, &end);\n\tgtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2,\n\t\t\t\t\t NULL);\n}\n\n\n/* Main Windows Callbacks */\n\nvoid on_save_activate(GtkMenuItem * menuitem, gpointer user_data);\ngboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,\n\t\t\t\t gpointer user_data)\n{\n\tGtkWidget *dialog, *label;\n\tgint result;\n\n\tif (!conf_get_changed())\n\t\treturn FALSE;\n\n\tdialog = gtk_dialog_new_with_buttons(_(\"Warning !\"),\n\t\t\t\t\t     GTK_WINDOW(main_wnd),\n\t\t\t\t\t     (GtkDialogFlags)\n\t\t\t\t\t     (GTK_DIALOG_MODAL |\n\t\t\t\t\t      GTK_DIALOG_DESTROY_WITH_PARENT),\n\t\t\t\t\t     GTK_STOCK_OK,\n\t\t\t\t\t     GTK_RESPONSE_YES,\n\t\t\t\t\t     GTK_STOCK_NO,\n\t\t\t\t\t     GTK_RESPONSE_NO,\n\t\t\t\t\t     GTK_STOCK_CANCEL,\n\t\t\t\t\t     GTK_RESPONSE_CANCEL, NULL);\n\tgtk_dialog_set_default_response(GTK_DIALOG(dialog),\n\t\t\t\t\tGTK_RESPONSE_CANCEL);\n\n\tlabel = gtk_label_new(_(\"\\nSave configuration ?\\n\"));\n\tgtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);\n\tgtk_widget_show(label);\n\n\tresult = gtk_dialog_run(GTK_DIALOG(dialog));\n\tswitch (result) {\n\tcase GTK_RESPONSE_YES:\n\t\ton_save_activate(NULL, NULL);\n\t\treturn FALSE;\n\tcase GTK_RESPONSE_NO:\n\t\treturn FALSE;\n\tcase GTK_RESPONSE_CANCEL:\n\tcase GTK_RESPONSE_DELETE_EVENT:\n\tdefault:\n\t\tgtk_widget_destroy(dialog);\n\t\treturn TRUE;\n\t}\n\n\treturn FALSE;\n}\n\n\nvoid on_window1_destroy(GtkObject * object, gpointer user_data)\n{\n\tgtk_main_quit();\n}\n\n\nvoid\non_window1_size_request(GtkWidget * widget,\n\t\t\tGtkRequisition * requisition, gpointer user_data)\n{\n\tstatic gint old_h;\n\tgint w, h;\n\n\tif (widget->window == NULL)\n\t\tgtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);\n\telse\n\t\tgdk_window_get_size(widget->window, &w, &h);\n\n\tif (h == old_h)\n\t\treturn;\n\told_h = h;\n\n\tgtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3);\n}\n\n\n/* Menu & Toolbar Callbacks */\n\n\nstatic void\nload_filename(GtkFileSelection * file_selector, gpointer user_data)\n{\n\tconst gchar *fn;\n\n\tfn = gtk_file_selection_get_filename(GTK_FILE_SELECTION\n\t\t\t\t\t     (user_data));\n\n\tif (conf_read(fn))\n\t\ttext_insert_msg(_(\"Error\"), _(\"Unable to load configuration !\"));\n\telse\n\t\tdisplay_tree(&rootmenu);\n}\n\nvoid on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkWidget *fs;\n\n\tfs = gtk_file_selection_new(_(\"Load file...\"));\n\tg_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),\n\t\t\t \"clicked\",\n\t\t\t G_CALLBACK(load_filename), (gpointer) fs);\n\tg_signal_connect_swapped(GTK_OBJECT\n\t\t\t\t (GTK_FILE_SELECTION(fs)->ok_button),\n\t\t\t\t \"clicked\", G_CALLBACK(gtk_widget_destroy),\n\t\t\t\t (gpointer) fs);\n\tg_signal_connect_swapped(GTK_OBJECT\n\t\t\t\t (GTK_FILE_SELECTION(fs)->cancel_button),\n\t\t\t\t \"clicked\", G_CALLBACK(gtk_widget_destroy),\n\t\t\t\t (gpointer) fs);\n\tgtk_widget_show(fs);\n}\n\n\nvoid on_save_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tif (conf_write(NULL))\n\t\ttext_insert_msg(_(\"Error\"), _(\"Unable to save configuration !\"));\n}\n\n\nstatic void\nstore_filename(GtkFileSelection * file_selector, gpointer user_data)\n{\n\tconst gchar *fn;\n\n\tfn = gtk_file_selection_get_filename(GTK_FILE_SELECTION\n\t\t\t\t\t     (user_data));\n\n\tif (conf_write(fn))\n\t\ttext_insert_msg(_(\"Error\"), _(\"Unable to save configuration !\"));\n\n\tgtk_widget_destroy(GTK_WIDGET(user_data));\n}\n\nvoid on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkWidget *fs;\n\n\tfs = gtk_file_selection_new(_(\"Save file as...\"));\n\tg_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),\n\t\t\t \"clicked\",\n\t\t\t G_CALLBACK(store_filename), (gpointer) fs);\n\tg_signal_connect_swapped(GTK_OBJECT\n\t\t\t\t (GTK_FILE_SELECTION(fs)->ok_button),\n\t\t\t\t \"clicked\", G_CALLBACK(gtk_widget_destroy),\n\t\t\t\t (gpointer) fs);\n\tg_signal_connect_swapped(GTK_OBJECT\n\t\t\t\t (GTK_FILE_SELECTION(fs)->cancel_button),\n\t\t\t\t \"clicked\", G_CALLBACK(gtk_widget_destroy),\n\t\t\t\t (gpointer) fs);\n\tgtk_widget_show(fs);\n}\n\n\nvoid on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tif (!on_window1_delete_event(NULL, NULL, NULL))\n\t\tgtk_widget_destroy(GTK_WIDGET(main_wnd));\n}\n\n\nvoid on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkTreeViewColumn *col;\n\n\tshow_name = GTK_CHECK_MENU_ITEM(menuitem)->active;\n\tcol = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME);\n\tif (col)\n\t\tgtk_tree_view_column_set_visible(col, show_name);\n}\n\n\nvoid on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkTreeViewColumn *col;\n\n\tshow_range = GTK_CHECK_MENU_ITEM(menuitem)->active;\n\tcol = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO);\n\tif (col)\n\t\tgtk_tree_view_column_set_visible(col, show_range);\n\tcol = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD);\n\tif (col)\n\t\tgtk_tree_view_column_set_visible(col, show_range);\n\tcol = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES);\n\tif (col)\n\t\tgtk_tree_view_column_set_visible(col, show_range);\n\n}\n\n\nvoid on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkTreeViewColumn *col;\n\n\tshow_value = GTK_CHECK_MENU_ITEM(menuitem)->active;\n\tcol = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE);\n\tif (col)\n\t\tgtk_tree_view_column_set_visible(col, show_value);\n}\n\n\nvoid\non_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)\n{\n\topt_mode = OPT_NORMAL;\n\tgtk_tree_store_clear(tree2);\n\tdisplay_tree(&rootmenu);\t/* instead of update_tree to speed-up */\n}\n\n\nvoid\non_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data)\n{\n\topt_mode = OPT_ALL;\n\tgtk_tree_store_clear(tree2);\n\tdisplay_tree(&rootmenu);\t/* instead of update_tree to speed-up */\n}\n\n\nvoid\non_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)\n{\n\topt_mode = OPT_PROMPT;\n\tgtk_tree_store_clear(tree2);\n\tdisplay_tree(&rootmenu);\t/* instead of update_tree to speed-up */\n}\n\n\nvoid on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkWidget *dialog;\n\tconst gchar *intro_text = _(\n\t    \"Welcome to gkc, the GTK+ graphical configuration tool\\n\"\n\t    \"For each option, a blank box indicates the feature is disabled, a\\n\"\n\t    \"check indicates it is enabled, and a dot indicates that it is to\\n\"\n\t    \"be compiled as a module.  Clicking on the box will cycle through the three states.\\n\"\n\t    \"\\n\"\n\t    \"If you do not see an option (e.g., a device driver) that you\\n\"\n\t    \"believe should be present, try turning on Show All Options\\n\"\n\t    \"under the Options menu.\\n\"\n\t    \"Although there is no cross reference yet to help you figure out\\n\"\n\t    \"what other options must be enabled to support the option you\\n\"\n\t    \"are interested in, you can still view the help of a grayed-out\\n\"\n\t    \"option.\\n\"\n\t    \"\\n\"\n\t    \"Toggling Show Debug Info under the Options menu will show \\n\"\n\t    \"the dependencies, which you can then match by examining other options.\");\n\n\tdialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),\n\t\t\t\t\tGTK_DIALOG_DESTROY_WITH_PARENT,\n\t\t\t\t\tGTK_MESSAGE_INFO,\n\t\t\t\t\tGTK_BUTTONS_CLOSE, \"%s\", intro_text);\n\tg_signal_connect_swapped(GTK_OBJECT(dialog), \"response\",\n\t\t\t\t G_CALLBACK(gtk_widget_destroy),\n\t\t\t\t GTK_OBJECT(dialog));\n\tgtk_widget_show_all(dialog);\n}\n\n\nvoid on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkWidget *dialog;\n\tconst gchar *about_text =\n\t    _(\"gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\\n\"\n\t      \"Based on the source code from Roman Zippel.\\n\");\n\n\tdialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),\n\t\t\t\t\tGTK_DIALOG_DESTROY_WITH_PARENT,\n\t\t\t\t\tGTK_MESSAGE_INFO,\n\t\t\t\t\tGTK_BUTTONS_CLOSE, \"%s\", about_text);\n\tg_signal_connect_swapped(GTK_OBJECT(dialog), \"response\",\n\t\t\t\t G_CALLBACK(gtk_widget_destroy),\n\t\t\t\t GTK_OBJECT(dialog));\n\tgtk_widget_show_all(dialog);\n}\n\n\nvoid on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)\n{\n\tGtkWidget *dialog;\n\tconst gchar *license_text =\n\t    _(\"gkc is released under the terms of the GNU GPL v2.\\n\"\n\t      \"For more information, please see the source code or\\n\"\n\t      \"visit http://www.fsf.org/licenses/licenses.html\\n\");\n\n\tdialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),\n\t\t\t\t\tGTK_DIALOG_DESTROY_WITH_PARENT,\n\t\t\t\t\tGTK_MESSAGE_INFO,\n\t\t\t\t\tGTK_BUTTONS_CLOSE, \"%s\", license_text);\n\tg_signal_connect_swapped(GTK_OBJECT(dialog), \"response\",\n\t\t\t\t G_CALLBACK(gtk_widget_destroy),\n\t\t\t\t GTK_OBJECT(dialog));\n\tgtk_widget_show_all(dialog);\n}\n\n\nvoid on_back_clicked(GtkButton * button, gpointer user_data)\n{\n\tenum prop_type ptype;\n\n\tcurrent = current->parent;\n\tptype = current->prompt ? current->prompt->type : P_UNKNOWN;\n\tif (ptype != P_MENU)\n\t\tcurrent = current->parent;\n\tdisplay_tree_part();\n\n\tif (current == &rootmenu)\n\t\tgtk_widget_set_sensitive(back_btn, FALSE);\n}\n\n\nvoid on_load_clicked(GtkButton * button, gpointer user_data)\n{\n\ton_load1_activate(NULL, user_data);\n}\n\n\nvoid on_single_clicked(GtkButton * button, gpointer user_data)\n{\n\tview_mode = SINGLE_VIEW;\n\tgtk_widget_hide(tree1_w);\n\tcurrent = &rootmenu;\n\tdisplay_tree_part();\n}\n\n\nvoid on_split_clicked(GtkButton * button, gpointer user_data)\n{\n\tgint w, h;\n\tview_mode = SPLIT_VIEW;\n\tgtk_widget_show(tree1_w);\n\tgtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h);\n\tgtk_paned_set_position(GTK_PANED(hpaned), w / 2);\n\tif (tree2)\n\t\tgtk_tree_store_clear(tree2);\n\tdisplay_list();\n\n\t/* Disable back btn, like in full mode. */\n\tgtk_widget_set_sensitive(back_btn, FALSE);\n}\n\n\nvoid on_full_clicked(GtkButton * button, gpointer user_data)\n{\n\tview_mode = FULL_VIEW;\n\tgtk_widget_hide(tree1_w);\n\tif (tree2)\n\t\tgtk_tree_store_clear(tree2);\n\tdisplay_tree(&rootmenu);\n\tgtk_widget_set_sensitive(back_btn, FALSE);\n}\n\n\nvoid on_collapse_clicked(GtkButton * button, gpointer user_data)\n{\n\tgtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w));\n}\n\n\nvoid on_expand_clicked(GtkButton * button, gpointer user_data)\n{\n\tgtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));\n}\n\n\n/* CTree Callbacks */\n\n/* Change hex/int/string value in the cell */\nstatic void renderer_edited(GtkCellRendererText * cell,\n\t\t\t    const gchar * path_string,\n\t\t\t    const gchar * new_text, gpointer user_data)\n{\n\tGtkTreePath *path = gtk_tree_path_new_from_string(path_string);\n\tGtkTreeIter iter;\n\tconst char *old_def, *new_def;\n\tstruct menu *menu;\n\tstruct symbol *sym;\n\n\tif (!gtk_tree_model_get_iter(model2, &iter, path))\n\t\treturn;\n\n\tgtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);\n\tsym = menu->sym;\n\n\tgtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1);\n\tnew_def = new_text;\n\n\tsym_set_string_value(sym, new_def);\n\n\tupdate_tree(&rootmenu, NULL);\n\n\tgtk_tree_path_free(path);\n}\n\n/* Change the value of a symbol and update the tree */\nstatic void change_sym_value(struct menu *menu, gint col)\n{\n\tstruct symbol *sym = menu->sym;\n\ttristate newval;\n\n\tif (!sym)\n\t\treturn;\n\n\tif (col == COL_NO)\n\t\tnewval = no;\n\telse if (col == COL_MOD)\n\t\tnewval = mod;\n\telse if (col == COL_YES)\n\t\tnewval = yes;\n\telse\n\t\treturn;\n\n\tswitch (sym_get_type(sym)) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tif (!sym_tristate_within_range(sym, newval))\n\t\t\tnewval = yes;\n\t\tsym_set_tristate_value(sym, newval);\n\t\tif (view_mode == FULL_VIEW)\n\t\t\tupdate_tree(&rootmenu, NULL);\n\t\telse if (view_mode == SPLIT_VIEW) {\n\t\t\tupdate_tree(browsed, NULL);\n\t\t\tdisplay_list();\n\t\t}\n\t\telse if (view_mode == SINGLE_VIEW)\n\t\t\tdisplay_tree_part();\t//fixme: keep exp/coll\n\t\tbreak;\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nstatic void toggle_sym_value(struct menu *menu)\n{\n\tif (!menu->sym)\n\t\treturn;\n\n\tsym_toggle_tristate_value(menu->sym);\n\tif (view_mode == FULL_VIEW)\n\t\tupdate_tree(&rootmenu, NULL);\n\telse if (view_mode == SPLIT_VIEW) {\n\t\tupdate_tree(browsed, NULL);\n\t\tdisplay_list();\n\t}\n\telse if (view_mode == SINGLE_VIEW)\n\t\tdisplay_tree_part();\t//fixme: keep exp/coll\n}\n\nstatic gint column2index(GtkTreeViewColumn * column)\n{\n\tgint i;\n\n\tfor (i = 0; i < COL_NUMBER; i++) {\n\t\tGtkTreeViewColumn *col;\n\n\t\tcol = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i);\n\t\tif (col == column)\n\t\t\treturn i;\n\t}\n\n\treturn -1;\n}\n\n\n/* User click: update choice (full) or goes down (single) */\ngboolean\non_treeview2_button_press_event(GtkWidget * widget,\n\t\t\t\tGdkEventButton * event, gpointer user_data)\n{\n\tGtkTreeView *view = GTK_TREE_VIEW(widget);\n\tGtkTreePath *path;\n\tGtkTreeViewColumn *column;\n\tGtkTreeIter iter;\n\tstruct menu *menu;\n\tgint col;\n\n#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK\n\tgint tx = (gint) event->x;\n\tgint ty = (gint) event->y;\n\tgint cx, cy;\n\n\tgtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,\n\t\t\t\t      &cy);\n#else\n\tgtk_tree_view_get_cursor(view, &path, &column);\n#endif\n\tif (path == NULL)\n\t\treturn FALSE;\n\n\tif (!gtk_tree_model_get_iter(model2, &iter, path))\n\t\treturn FALSE;\n\tgtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);\n\n\tcol = column2index(column);\n\tif (event->type == GDK_2BUTTON_PRESS) {\n\t\tenum prop_type ptype;\n\t\tptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\n\t\tif (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) {\n\t\t\t// goes down into menu\n\t\t\tcurrent = menu;\n\t\t\tdisplay_tree_part();\n\t\t\tgtk_widget_set_sensitive(back_btn, TRUE);\n\t\t} else if ((col == COL_OPTION)) {\n\t\t\ttoggle_sym_value(menu);\n\t\t\tgtk_tree_view_expand_row(view, path, TRUE);\n\t\t}\n\t} else {\n\t\tif (col == COL_VALUE) {\n\t\t\ttoggle_sym_value(menu);\n\t\t\tgtk_tree_view_expand_row(view, path, TRUE);\n\t\t} else if (col == COL_NO || col == COL_MOD\n\t\t\t   || col == COL_YES) {\n\t\t\tchange_sym_value(menu, col);\n\t\t\tgtk_tree_view_expand_row(view, path, TRUE);\n\t\t}\n\t}\n\n\treturn FALSE;\n}\n\n/* Key pressed: update choice */\ngboolean\non_treeview2_key_press_event(GtkWidget * widget,\n\t\t\t     GdkEventKey * event, gpointer user_data)\n{\n\tGtkTreeView *view = GTK_TREE_VIEW(widget);\n\tGtkTreePath *path;\n\tGtkTreeViewColumn *column;\n\tGtkTreeIter iter;\n\tstruct menu *menu;\n\tgint col;\n\n\tgtk_tree_view_get_cursor(view, &path, &column);\n\tif (path == NULL)\n\t\treturn FALSE;\n\n\tif (event->keyval == GDK_space) {\n\t\tif (gtk_tree_view_row_expanded(view, path))\n\t\t\tgtk_tree_view_collapse_row(view, path);\n\t\telse\n\t\t\tgtk_tree_view_expand_row(view, path, FALSE);\n\t\treturn TRUE;\n\t}\n\tif (event->keyval == GDK_KP_Enter) {\n\t}\n\tif (widget == tree1_w)\n\t\treturn FALSE;\n\n\tgtk_tree_model_get_iter(model2, &iter, path);\n\tgtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);\n\n\tif (!strcasecmp(event->string, \"n\"))\n\t\tcol = COL_NO;\n\telse if (!strcasecmp(event->string, \"m\"))\n\t\tcol = COL_MOD;\n\telse if (!strcasecmp(event->string, \"y\"))\n\t\tcol = COL_YES;\n\telse\n\t\tcol = -1;\n\tchange_sym_value(menu, col);\n\n\treturn FALSE;\n}\n\n\n/* Row selection changed: update help */\nvoid\non_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data)\n{\n\tGtkTreeSelection *selection;\n\tGtkTreeIter iter;\n\tstruct menu *menu;\n\n\tselection = gtk_tree_view_get_selection(treeview);\n\tif (gtk_tree_selection_get_selected(selection, &model2, &iter)) {\n\t\tgtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1);\n\t\ttext_insert_help(menu);\n\t}\n}\n\n\n/* User click: display sub-tree in the right frame. */\ngboolean\non_treeview1_button_press_event(GtkWidget * widget,\n\t\t\t\tGdkEventButton * event, gpointer user_data)\n{\n\tGtkTreeView *view = GTK_TREE_VIEW(widget);\n\tGtkTreePath *path;\n\tGtkTreeViewColumn *column;\n\tGtkTreeIter iter;\n\tstruct menu *menu;\n\n\tgint tx = (gint) event->x;\n\tgint ty = (gint) event->y;\n\tgint cx, cy;\n\n\tgtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx,\n\t\t\t\t      &cy);\n\tif (path == NULL)\n\t\treturn FALSE;\n\n\tgtk_tree_model_get_iter(model1, &iter, path);\n\tgtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1);\n\n\tif (event->type == GDK_2BUTTON_PRESS) {\n\t\ttoggle_sym_value(menu);\n\t\tcurrent = menu;\n\t\tdisplay_tree_part();\n\t} else {\n\t\tbrowsed = menu;\n\t\tdisplay_tree_part();\n\t}\n\n\tgtk_widget_realize(tree2_w);\n\tgtk_tree_view_set_cursor(view, path, NULL, FALSE);\n\tgtk_widget_grab_focus(tree2_w);\n\n\treturn FALSE;\n}\n\n\n/* Fill a row of strings */\nstatic gchar **fill_row(struct menu *menu)\n{\n\tstatic gchar *row[COL_NUMBER];\n\tstruct symbol *sym = menu->sym;\n\tconst char *def;\n\tint stype;\n\ttristate val;\n\tenum prop_type ptype;\n\tint i;\n\n\tfor (i = COL_OPTION; i <= COL_COLOR; i++)\n\t\tg_free(row[i]);\n\tbzero(row, sizeof(row));\n\n\trow[COL_OPTION] =\n\t    g_strdup_printf(\"%s %s\", _(menu_get_prompt(menu)),\n\t\t\t    sym && !sym_has_value(sym) ? \"(NEW)\" : \"\");\n\n\tif (opt_mode == OPT_ALL && !menu_is_visible(menu))\n\t\trow[COL_COLOR] = g_strdup(\"DarkGray\");\n\telse if (opt_mode == OPT_PROMPT &&\n\t\t\tmenu_has_prompt(menu) && !menu_is_visible(menu))\n\t\trow[COL_COLOR] = g_strdup(\"DarkGray\");\n\telse\n\t\trow[COL_COLOR] = g_strdup(\"Black\");\n\n\tptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\tswitch (ptype) {\n\tcase P_MENU:\n\t\trow[COL_PIXBUF] = (gchar *) xpm_menu;\n\t\tif (view_mode == SINGLE_VIEW)\n\t\t\trow[COL_PIXVIS] = GINT_TO_POINTER(TRUE);\n\t\trow[COL_BTNVIS] = GINT_TO_POINTER(FALSE);\n\t\tbreak;\n\tcase P_COMMENT:\n\t\trow[COL_PIXBUF] = (gchar *) xpm_void;\n\t\trow[COL_PIXVIS] = GINT_TO_POINTER(FALSE);\n\t\trow[COL_BTNVIS] = GINT_TO_POINTER(FALSE);\n\t\tbreak;\n\tdefault:\n\t\trow[COL_PIXBUF] = (gchar *) xpm_void;\n\t\trow[COL_PIXVIS] = GINT_TO_POINTER(FALSE);\n\t\trow[COL_BTNVIS] = GINT_TO_POINTER(TRUE);\n\t\tbreak;\n\t}\n\n\tif (!sym)\n\t\treturn row;\n\trow[COL_NAME] = g_strdup(sym->name);\n\n\tsym_calc_value(sym);\n\tsym->flags &= ~SYMBOL_CHANGED;\n\n\tif (sym_is_choice(sym)) {\t// parse childs for getting final value\n\t\tstruct menu *child;\n\t\tstruct symbol *def_sym = sym_get_choice_value(sym);\n\t\tstruct menu *def_menu = NULL;\n\n\t\trow[COL_BTNVIS] = GINT_TO_POINTER(FALSE);\n\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (menu_is_visible(child)\n\t\t\t    && child->sym == def_sym)\n\t\t\t\tdef_menu = child;\n\t\t}\n\n\t\tif (def_menu)\n\t\t\trow[COL_VALUE] =\n\t\t\t    g_strdup(_(menu_get_prompt(def_menu)));\n\t}\n\tif (sym->flags & SYMBOL_CHOICEVAL)\n\t\trow[COL_BTNRAD] = GINT_TO_POINTER(TRUE);\n\n\tstype = sym_get_type(sym);\n\tswitch (stype) {\n\tcase S_BOOLEAN:\n\t\tif (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE)\n\t\t\trow[COL_BTNVIS] = GINT_TO_POINTER(TRUE);\n\t\tif (sym_is_choice(sym))\n\t\t\tbreak;\n\t\t/* fall through */\n\tcase S_TRISTATE:\n\t\tval = sym_get_tristate_value(sym);\n\t\tswitch (val) {\n\t\tcase no:\n\t\t\trow[COL_NO] = g_strdup(\"N\");\n\t\t\trow[COL_VALUE] = g_strdup(\"N\");\n\t\t\trow[COL_BTNACT] = GINT_TO_POINTER(FALSE);\n\t\t\trow[COL_BTNINC] = GINT_TO_POINTER(FALSE);\n\t\t\tbreak;\n\t\tcase mod:\n\t\t\trow[COL_MOD] = g_strdup(\"M\");\n\t\t\trow[COL_VALUE] = g_strdup(\"M\");\n\t\t\trow[COL_BTNINC] = GINT_TO_POINTER(TRUE);\n\t\t\tbreak;\n\t\tcase yes:\n\t\t\trow[COL_YES] = g_strdup(\"Y\");\n\t\t\trow[COL_VALUE] = g_strdup(\"Y\");\n\t\t\trow[COL_BTNACT] = GINT_TO_POINTER(TRUE);\n\t\t\trow[COL_BTNINC] = GINT_TO_POINTER(FALSE);\n\t\t\tbreak;\n\t\t}\n\n\t\tif (val != no && sym_tristate_within_range(sym, no))\n\t\t\trow[COL_NO] = g_strdup(\"_\");\n\t\tif (val != mod && sym_tristate_within_range(sym, mod))\n\t\t\trow[COL_MOD] = g_strdup(\"_\");\n\t\tif (val != yes && sym_tristate_within_range(sym, yes))\n\t\t\trow[COL_YES] = g_strdup(\"_\");\n\t\tbreak;\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tdef = sym_get_string_value(sym);\n\t\trow[COL_VALUE] = g_strdup(def);\n\t\trow[COL_EDIT] = GINT_TO_POINTER(TRUE);\n\t\trow[COL_BTNVIS] = GINT_TO_POINTER(FALSE);\n\t\tbreak;\n\t}\n\n\treturn row;\n}\n\n\n/* Set the node content with a row of strings */\nstatic void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row)\n{\n\tGdkColor color;\n\tgboolean success;\n\tGdkPixbuf *pix;\n\n\tpix = gdk_pixbuf_new_from_xpm_data((const char **)\n\t\t\t\t\t   row[COL_PIXBUF]);\n\n\tgdk_color_parse(row[COL_COLOR], &color);\n\tgdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1,\n\t\t\t\t  FALSE, FALSE, &success);\n\n\tgtk_tree_store_set(tree, node,\n\t\t\t   COL_OPTION, row[COL_OPTION],\n\t\t\t   COL_NAME, row[COL_NAME],\n\t\t\t   COL_NO, row[COL_NO],\n\t\t\t   COL_MOD, row[COL_MOD],\n\t\t\t   COL_YES, row[COL_YES],\n\t\t\t   COL_VALUE, row[COL_VALUE],\n\t\t\t   COL_MENU, (gpointer) menu,\n\t\t\t   COL_COLOR, &color,\n\t\t\t   COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]),\n\t\t\t   COL_PIXBUF, pix,\n\t\t\t   COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]),\n\t\t\t   COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]),\n\t\t\t   COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]),\n\t\t\t   COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]),\n\t\t\t   COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]),\n\t\t\t   -1);\n\n\tg_object_unref(pix);\n}\n\n\n/* Add a node to the tree */\nstatic void place_node(struct menu *menu, char **row)\n{\n\tGtkTreeIter *parent = parents[indent - 1];\n\tGtkTreeIter *node = parents[indent];\n\n\tgtk_tree_store_append(tree, node, parent);\n\tset_node(node, menu, row);\n}\n\n\n/* Find a node in the GTK+ tree */\nstatic GtkTreeIter found;\n\n/*\n * Find a menu in the GtkTree starting at parent.\n */\nGtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent,\n\t\t\t\t    struct menu *tofind)\n{\n\tGtkTreeIter iter;\n\tGtkTreeIter *child = &iter;\n\tgboolean valid;\n\tGtkTreeIter *ret;\n\n\tvalid = gtk_tree_model_iter_children(model2, child, parent);\n\twhile (valid) {\n\t\tstruct menu *menu;\n\n\t\tgtk_tree_model_get(model2, child, 6, &menu, -1);\n\n\t\tif (menu == tofind) {\n\t\t\tmemcpy(&found, child, sizeof(GtkTreeIter));\n\t\t\treturn &found;\n\t\t}\n\n\t\tret = gtktree_iter_find_node(child, tofind);\n\t\tif (ret)\n\t\t\treturn ret;\n\n\t\tvalid = gtk_tree_model_iter_next(model2, child);\n\t}\n\n\treturn NULL;\n}\n\n\n/*\n * Update the tree by adding/removing entries\n * Does not change other nodes\n */\nstatic void update_tree(struct menu *src, GtkTreeIter * dst)\n{\n\tstruct menu *child1;\n\tGtkTreeIter iter, tmp;\n\tGtkTreeIter *child2 = &iter;\n\tgboolean valid;\n\tGtkTreeIter *sibling;\n\tstruct symbol *sym;\n\tstruct menu *menu1, *menu2;\n\n\tif (src == &rootmenu)\n\t\tindent = 1;\n\n\tvalid = gtk_tree_model_iter_children(model2, child2, dst);\n\tfor (child1 = src->list; child1; child1 = child1->next) {\n\n\t\tsym = child1->sym;\n\n\t      reparse:\n\t\tmenu1 = child1;\n\t\tif (valid)\n\t\t\tgtk_tree_model_get(model2, child2, COL_MENU,\n\t\t\t\t\t   &menu2, -1);\n\t\telse\n\t\t\tmenu2 = NULL;\t// force adding of a first child\n\n#ifdef DEBUG\n\t\tprintf(\"%*c%s | %s\\n\", indent, ' ',\n\t\t       menu1 ? menu_get_prompt(menu1) : \"nil\",\n\t\t       menu2 ? menu_get_prompt(menu2) : \"nil\");\n#endif\n\n\t\tif ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||\n\t\t    (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||\n\t\t    (opt_mode == OPT_ALL    && !menu_get_prompt(child1))) {\n\n\t\t\t/* remove node */\n\t\t\tif (gtktree_iter_find_node(dst, menu1) != NULL) {\n\t\t\t\tmemcpy(&tmp, child2, sizeof(GtkTreeIter));\n\t\t\t\tvalid = gtk_tree_model_iter_next(model2,\n\t\t\t\t\t\t\t\t child2);\n\t\t\t\tgtk_tree_store_remove(tree2, &tmp);\n\t\t\t\tif (!valid)\n\t\t\t\t\treturn;\t\t/* next parent */\n\t\t\t\telse\n\t\t\t\t\tgoto reparse;\t/* next child */\n\t\t\t} else\n\t\t\t\tcontinue;\n\t\t}\n\n\t\tif (menu1 != menu2) {\n\t\t\tif (gtktree_iter_find_node(dst, menu1) == NULL) {\t// add node\n\t\t\t\tif (!valid && !menu2)\n\t\t\t\t\tsibling = NULL;\n\t\t\t\telse\n\t\t\t\t\tsibling = child2;\n\t\t\t\tgtk_tree_store_insert_before(tree2,\n\t\t\t\t\t\t\t     child2,\n\t\t\t\t\t\t\t     dst, sibling);\n\t\t\t\tset_node(child2, menu1, fill_row(menu1));\n\t\t\t\tif (menu2 == NULL)\n\t\t\t\t\tvalid = TRUE;\n\t\t\t} else {\t// remove node\n\t\t\t\tmemcpy(&tmp, child2, sizeof(GtkTreeIter));\n\t\t\t\tvalid = gtk_tree_model_iter_next(model2,\n\t\t\t\t\t\t\t\t child2);\n\t\t\t\tgtk_tree_store_remove(tree2, &tmp);\n\t\t\t\tif (!valid)\n\t\t\t\t\treturn;\t// next parent\n\t\t\t\telse\n\t\t\t\t\tgoto reparse;\t// next child\n\t\t\t}\n\t\t} else if (sym && (sym->flags & SYMBOL_CHANGED)) {\n\t\t\tset_node(child2, menu1, fill_row(menu1));\n\t\t}\n\n\t\tindent++;\n\t\tupdate_tree(child1, child2);\n\t\tindent--;\n\n\t\tvalid = gtk_tree_model_iter_next(model2, child2);\n\t}\n}\n\n\n/* Display the whole tree (single/split/full view) */\nstatic void display_tree(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct menu *child;\n\tenum prop_type ptype;\n\n\tif (menu == &rootmenu) {\n\t\tindent = 1;\n\t\tcurrent = &rootmenu;\n\t}\n\n\tfor (child = menu->list; child; child = child->next) {\n\t\tprop = child->prompt;\n\t\tsym = child->sym;\n\t\tptype = prop ? prop->type : P_UNKNOWN;\n\n\t\tif (sym)\n\t\t\tsym->flags &= ~SYMBOL_CHANGED;\n\n\t\tif ((view_mode == SPLIT_VIEW)\n\t\t    && !(child->flags & MENU_ROOT) && (tree == tree1))\n\t\t\tcontinue;\n\n\t\tif ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT)\n\t\t    && (tree == tree2))\n\t\t\tcontinue;\n\n\t\tif ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||\n\t\t    (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||\n\t\t    (opt_mode == OPT_ALL    && menu_get_prompt(child)))\n\t\t\tplace_node(child, fill_row(child));\n#ifdef DEBUG\n\t\tprintf(\"%*c%s: \", indent, ' ', menu_get_prompt(child));\n\t\tprintf(\"%s\", child->flags & MENU_ROOT ? \"rootmenu | \" : \"\");\n\t\tprintf(\"%s\", prop_get_type_name(ptype));\n\t\tprintf(\" | \");\n\t\tif (sym) {\n\t\t\tprintf(\"%s\", sym_type_name(sym->type));\n\t\t\tprintf(\" | \");\n\t\t\tprintf(\"%s\", dbg_sym_flags(sym->flags));\n\t\t\tprintf(\"\\n\");\n\t\t} else\n\t\t\tprintf(\"\\n\");\n#endif\n\t\tif ((view_mode != FULL_VIEW) && (ptype == P_MENU)\n\t\t    && (tree == tree2))\n\t\t\tcontinue;\n/*\n                if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT))\n\t\t    || (view_mode == FULL_VIEW)\n\t\t    || (view_mode == SPLIT_VIEW))*/\n\n\t\t/* Change paned position if the view is not in 'split mode' */\n\t\tif (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) {\n\t\t\tgtk_paned_set_position(GTK_PANED(hpaned), 0);\n\t\t}\n\n\t\tif (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT))\n\t\t    || (view_mode == FULL_VIEW)\n\t\t    || (view_mode == SPLIT_VIEW)) {\n\t\t\tindent++;\n\t\t\tdisplay_tree(child);\n\t\t\tindent--;\n\t\t}\n\t}\n}\n\n/* Display a part of the tree starting at current node (single/split view) */\nstatic void display_tree_part(void)\n{\n\tif (tree2)\n\t\tgtk_tree_store_clear(tree2);\n\tif (view_mode == SINGLE_VIEW)\n\t\tdisplay_tree(current);\n\telse if (view_mode == SPLIT_VIEW)\n\t\tdisplay_tree(browsed);\n\tgtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w));\n}\n\n/* Display the list in the left frame (split view) */\nstatic void display_list(void)\n{\n\tif (tree1)\n\t\tgtk_tree_store_clear(tree1);\n\n\ttree = tree1;\n\tdisplay_tree(&rootmenu);\n\tgtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w));\n\ttree = tree2;\n}\n\nvoid fixup_rootmenu(struct menu *menu)\n{\n\tstruct menu *child;\n\tstatic int menu_cnt = 0;\n\n\tmenu->flags |= MENU_ROOT;\n\tfor (child = menu->list; child; child = child->next) {\n\t\tif (child->prompt && child->prompt->type == P_MENU) {\n\t\t\tmenu_cnt++;\n\t\t\tfixup_rootmenu(child);\n\t\t\tmenu_cnt--;\n\t\t} else if (!menu_cnt)\n\t\t\tfixup_rootmenu(child);\n\t}\n}\n\n\n/* Main */\nint main(int ac, char *av[])\n{\n\tconst char *name;\n\tchar *env;\n\tgchar *glade_file;\n\n\tbindtextdomain(PACKAGE, LOCALEDIR);\n\tbind_textdomain_codeset(PACKAGE, \"UTF-8\");\n\ttextdomain(PACKAGE);\n\n\t/* GTK stuffs */\n\tgtk_set_locale();\n\tgtk_init(&ac, &av);\n\tglade_init();\n\n\t//add_pixmap_directory (PACKAGE_DATA_DIR \"/\" PACKAGE \"/pixmaps\");\n\t//add_pixmap_directory (PACKAGE_SOURCE_DIR \"/pixmaps\");\n\n\t/* Determine GUI path */\n\tenv = getenv(SRCTREE);\n\tif (env)\n\t\tglade_file = g_strconcat(env, \"/scripts/kconfig/gconf.glade\", NULL);\n\telse if (av[0][0] == '/')\n\t\tglade_file = g_strconcat(av[0], \".glade\", NULL);\n\telse\n\t\tglade_file = g_strconcat(g_get_current_dir(), \"/\", av[0], \".glade\", NULL);\n\n\t/* Conf stuffs */\n\tif (ac > 1 && av[1][0] == '-') {\n\t\tswitch (av[1][1]) {\n\t\tcase 'a':\n\t\t\t//showAll = 1;\n\t\t\tbreak;\n\t\tcase 'h':\n\t\tcase '?':\n\t\t\tprintf(\"%s <config>\\n\", av[0]);\n\t\t\texit(0);\n\t\t}\n\t\tname = av[2];\n\t} else\n\t\tname = av[1];\n\n\tconf_parse(name);\n\tfixup_rootmenu(&rootmenu);\n\tconf_read(NULL);\n\n\t/* Load the interface and connect signals */\n\tinit_main_window(glade_file);\n\tinit_tree_model();\n\tinit_left_tree();\n\tinit_right_tree();\n\n\tswitch (view_mode) {\n\tcase SINGLE_VIEW:\n\t\tdisplay_tree_part();\n\t\tbreak;\n\tcase SPLIT_VIEW:\n\t\tdisplay_list();\n\t\tbreak;\n\tcase FULL_VIEW:\n\t\tdisplay_tree(&rootmenu);\n\t\tbreak;\n\t}\n\n\tgtk_main();\n\n\treturn 0;\n}\n\nstatic void conf_changed(void)\n{\n\tbool changed = conf_get_changed();\n\tgtk_widget_set_sensitive(save_btn, changed);\n\tgtk_widget_set_sensitive(save_menu_item, changed);\n}\n"
  },
  {
    "path": "kconfig/gconf.glade",
    "content": "<?xml version=\"1.0\" standalone=\"no\"?> <!--*- mode: xml -*-->\n\n<glade-interface>\n\n<widget class=\"GtkWindow\" id=\"window1\">\n  <property name=\"visible\">True</property>\n  <property name=\"title\" translatable=\"yes\">Gtk Kernel Configurator</property>\n  <property name=\"type\">GTK_WINDOW_TOPLEVEL</property>\n  <property name=\"window_position\">GTK_WIN_POS_NONE</property>\n  <property name=\"modal\">False</property>\n  <property name=\"default_width\">640</property>\n  <property name=\"default_height\">480</property>\n  <property name=\"resizable\">True</property>\n  <property name=\"destroy_with_parent\">False</property>\n  <property name=\"decorated\">True</property>\n  <property name=\"skip_taskbar_hint\">False</property>\n  <property name=\"skip_pager_hint\">False</property>\n  <property name=\"type_hint\">GDK_WINDOW_TYPE_HINT_NORMAL</property>\n  <property name=\"gravity\">GDK_GRAVITY_NORTH_WEST</property>\n  <signal name=\"destroy\" handler=\"on_window1_destroy\" object=\"window1\"/>\n  <signal name=\"size_request\" handler=\"on_window1_size_request\" object=\"vpaned1\" last_modification_time=\"Fri, 11 Jan 2002 16:17:11 GMT\"/>\n  <signal name=\"delete_event\" handler=\"on_window1_delete_event\" object=\"window1\" last_modification_time=\"Sun, 09 Mar 2003 19:42:46 GMT\"/>\n\n  <child>\n    <widget class=\"GtkVBox\" id=\"vbox1\">\n      <property name=\"visible\">True</property>\n      <property name=\"homogeneous\">False</property>\n      <property name=\"spacing\">0</property>\n\n      <child>\n\t<widget class=\"GtkMenuBar\" id=\"menubar1\">\n\t  <property name=\"visible\">True</property>\n\n\t  <child>\n\t    <widget class=\"GtkMenuItem\" id=\"file1\">\n\t      <property name=\"visible\">True</property>\n\t      <property name=\"label\" translatable=\"yes\">_File</property>\n\t      <property name=\"use_underline\">True</property>\n\n\t      <child>\n\t\t<widget class=\"GtkMenu\" id=\"file1_menu\">\n\n\t\t  <child>\n\t\t    <widget class=\"GtkImageMenuItem\" id=\"load1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Load a config file</property>\n\t\t      <property name=\"label\" translatable=\"yes\">_Load</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_load1_activate\"/>\n\t\t      <accelerator key=\"L\" modifiers=\"GDK_CONTROL_MASK\" signal=\"activate\"/>\n\n\t\t      <child internal-child=\"image\">\n\t\t\t<widget class=\"GtkImage\" id=\"image39\">\n\t\t\t  <property name=\"visible\">True</property>\n\t\t\t  <property name=\"stock\">gtk-open</property>\n\t\t\t  <property name=\"icon_size\">1</property>\n\t\t\t  <property name=\"xalign\">0.5</property>\n\t\t\t  <property name=\"yalign\">0.5</property>\n\t\t\t  <property name=\"xpad\">0</property>\n\t\t\t  <property name=\"ypad\">0</property>\n\t\t\t</widget>\n\t\t      </child>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkImageMenuItem\" id=\"save1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Save the config in .config</property>\n\t\t      <property name=\"label\" translatable=\"yes\">_Save</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_save_activate\"/>\n\t\t      <accelerator key=\"S\" modifiers=\"GDK_CONTROL_MASK\" signal=\"activate\"/>\n\n\t\t      <child internal-child=\"image\">\n\t\t\t<widget class=\"GtkImage\" id=\"image40\">\n\t\t\t  <property name=\"visible\">True</property>\n\t\t\t  <property name=\"stock\">gtk-save</property>\n\t\t\t  <property name=\"icon_size\">1</property>\n\t\t\t  <property name=\"xalign\">0.5</property>\n\t\t\t  <property name=\"yalign\">0.5</property>\n\t\t\t  <property name=\"xpad\">0</property>\n\t\t\t  <property name=\"ypad\">0</property>\n\t\t\t</widget>\n\t\t      </child>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkImageMenuItem\" id=\"save_as1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Save the config in a file</property>\n\t\t      <property name=\"label\" translatable=\"yes\">Save _as</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_save_as1_activate\"/>\n\n\t\t      <child internal-child=\"image\">\n\t\t\t<widget class=\"GtkImage\" id=\"image41\">\n\t\t\t  <property name=\"visible\">True</property>\n\t\t\t  <property name=\"stock\">gtk-save-as</property>\n\t\t\t  <property name=\"icon_size\">1</property>\n\t\t\t  <property name=\"xalign\">0.5</property>\n\t\t\t  <property name=\"yalign\">0.5</property>\n\t\t\t  <property name=\"xpad\">0</property>\n\t\t\t  <property name=\"ypad\">0</property>\n\t\t\t</widget>\n\t\t      </child>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkSeparatorMenuItem\" id=\"separator1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkImageMenuItem\" id=\"quit1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"label\" translatable=\"yes\">_Quit</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_quit1_activate\"/>\n\t\t      <accelerator key=\"Q\" modifiers=\"GDK_CONTROL_MASK\" signal=\"activate\"/>\n\n\t\t      <child internal-child=\"image\">\n\t\t\t<widget class=\"GtkImage\" id=\"image42\">\n\t\t\t  <property name=\"visible\">True</property>\n\t\t\t  <property name=\"stock\">gtk-quit</property>\n\t\t\t  <property name=\"icon_size\">1</property>\n\t\t\t  <property name=\"xalign\">0.5</property>\n\t\t\t  <property name=\"yalign\">0.5</property>\n\t\t\t  <property name=\"xpad\">0</property>\n\t\t\t  <property name=\"ypad\">0</property>\n\t\t\t</widget>\n\t\t      </child>\n\t\t    </widget>\n\t\t  </child>\n\t\t</widget>\n\t      </child>\n\t    </widget>\n\t  </child>\n\n\t  <child>\n\t    <widget class=\"GtkMenuItem\" id=\"options1\">\n\t      <property name=\"visible\">True</property>\n\t      <property name=\"label\" translatable=\"yes\">_Options</property>\n\t      <property name=\"use_underline\">True</property>\n\n\t      <child>\n\t\t<widget class=\"GtkMenu\" id=\"options1_menu\">\n\n\t\t  <child>\n\t\t    <widget class=\"GtkCheckMenuItem\" id=\"show_name1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Show name</property>\n\t\t      <property name=\"label\" translatable=\"yes\">Show _name</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <property name=\"active\">False</property>\n\t\t      <signal name=\"activate\" handler=\"on_show_name1_activate\"/>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkCheckMenuItem\" id=\"show_range1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Show range (Y/M/N)</property>\n\t\t      <property name=\"label\" translatable=\"yes\">Show _range</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <property name=\"active\">False</property>\n\t\t      <signal name=\"activate\" handler=\"on_show_range1_activate\"/>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkCheckMenuItem\" id=\"show_data1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Show value of the option</property>\n\t\t      <property name=\"label\" translatable=\"yes\">Show _data</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <property name=\"active\">False</property>\n\t\t      <signal name=\"activate\" handler=\"on_show_data1_activate\"/>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkSeparatorMenuItem\" id=\"separator2\">\n\t\t      <property name=\"visible\">True</property>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkRadioMenuItem\" id=\"set_option_mode1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Show normal options</property>\n\t\t      <property name=\"label\" translatable=\"yes\">Show normal options</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <property name=\"active\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_set_option_mode1_activate\"/>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkRadioMenuItem\" id=\"set_option_mode2\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Show all options</property>\n\t\t      <property name=\"label\" translatable=\"yes\">Show all _options</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <property name=\"active\">False</property>\n\t\t      <property name=\"group\">set_option_mode1</property>\n\t\t      <signal name=\"activate\" handler=\"on_set_option_mode2_activate\"/>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkRadioMenuItem\" id=\"set_option_mode3\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"tooltip\" translatable=\"yes\">Show all options with prompts</property>\n\t\t      <property name=\"label\" translatable=\"yes\">Show all prompt options</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <property name=\"active\">False</property>\n\t\t      <property name=\"group\">set_option_mode1</property>\n\t\t      <signal name=\"activate\" handler=\"on_set_option_mode3_activate\"/>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t</widget>\n\t      </child>\n\t    </widget>\n\t  </child>\n\n\t  <child>\n\t    <widget class=\"GtkMenuItem\" id=\"help1\">\n\t      <property name=\"visible\">True</property>\n\t      <property name=\"label\" translatable=\"yes\">_Help</property>\n\t      <property name=\"use_underline\">True</property>\n\n\t      <child>\n\t\t<widget class=\"GtkMenu\" id=\"help1_menu\">\n\n\t\t  <child>\n\t\t    <widget class=\"GtkImageMenuItem\" id=\"introduction1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"label\" translatable=\"yes\">_Introduction</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_introduction1_activate\" last_modification_time=\"Fri, 15 Nov 2002 20:26:30 GMT\"/>\n\t\t      <accelerator key=\"I\" modifiers=\"GDK_CONTROL_MASK\" signal=\"activate\"/>\n\n\t\t      <child internal-child=\"image\">\n\t\t\t<widget class=\"GtkImage\" id=\"image43\">\n\t\t\t  <property name=\"visible\">True</property>\n\t\t\t  <property name=\"stock\">gtk-dialog-question</property>\n\t\t\t  <property name=\"icon_size\">1</property>\n\t\t\t  <property name=\"xalign\">0.5</property>\n\t\t\t  <property name=\"yalign\">0.5</property>\n\t\t\t  <property name=\"xpad\">0</property>\n\t\t\t  <property name=\"ypad\">0</property>\n\t\t\t</widget>\n\t\t      </child>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkImageMenuItem\" id=\"about1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"label\" translatable=\"yes\">_About</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_about1_activate\" last_modification_time=\"Fri, 15 Nov 2002 20:26:30 GMT\"/>\n\t\t      <accelerator key=\"A\" modifiers=\"GDK_CONTROL_MASK\" signal=\"activate\"/>\n\n\t\t      <child internal-child=\"image\">\n\t\t\t<widget class=\"GtkImage\" id=\"image44\">\n\t\t\t  <property name=\"visible\">True</property>\n\t\t\t  <property name=\"stock\">gtk-properties</property>\n\t\t\t  <property name=\"icon_size\">1</property>\n\t\t\t  <property name=\"xalign\">0.5</property>\n\t\t\t  <property name=\"yalign\">0.5</property>\n\t\t\t  <property name=\"xpad\">0</property>\n\t\t\t  <property name=\"ypad\">0</property>\n\t\t\t</widget>\n\t\t      </child>\n\t\t    </widget>\n\t\t  </child>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkImageMenuItem\" id=\"license1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"label\" translatable=\"yes\">_License</property>\n\t\t      <property name=\"use_underline\">True</property>\n\t\t      <signal name=\"activate\" handler=\"on_license1_activate\" last_modification_time=\"Fri, 15 Nov 2002 20:26:30 GMT\"/>\n\n\t\t      <child internal-child=\"image\">\n\t\t\t<widget class=\"GtkImage\" id=\"image45\">\n\t\t\t  <property name=\"visible\">True</property>\n\t\t\t  <property name=\"stock\">gtk-justify-fill</property>\n\t\t\t  <property name=\"icon_size\">1</property>\n\t\t\t  <property name=\"xalign\">0.5</property>\n\t\t\t  <property name=\"yalign\">0.5</property>\n\t\t\t  <property name=\"xpad\">0</property>\n\t\t\t  <property name=\"ypad\">0</property>\n\t\t\t</widget>\n\t\t      </child>\n\t\t    </widget>\n\t\t  </child>\n\t\t</widget>\n\t      </child>\n\t    </widget>\n\t  </child>\n\t</widget>\n\t<packing>\n\t  <property name=\"padding\">0</property>\n\t  <property name=\"expand\">False</property>\n\t  <property name=\"fill\">False</property>\n\t</packing>\n      </child>\n\n      <child>\n\t<widget class=\"GtkHandleBox\" id=\"handlebox1\">\n\t  <property name=\"visible\">True</property>\n\t  <property name=\"shadow_type\">GTK_SHADOW_OUT</property>\n\t  <property name=\"handle_position\">GTK_POS_LEFT</property>\n\t  <property name=\"snap_edge\">GTK_POS_TOP</property>\n\n\t  <child>\n\t    <widget class=\"GtkToolbar\" id=\"toolbar1\">\n\t      <property name=\"visible\">True</property>\n\t      <property name=\"orientation\">GTK_ORIENTATION_HORIZONTAL</property>\n\t      <property name=\"toolbar_style\">GTK_TOOLBAR_BOTH</property>\n\t      <property name=\"tooltips\">True</property>\n\t      <property name=\"show_arrow\">True</property>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button1\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Goes up of one level (single view)</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Back</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-undo</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_back_clicked\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolItem\" id=\"toolitem1\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkVSeparator\" id=\"vseparator1\">\n\t\t      <property name=\"visible\">True</property>\n\t\t    </widget>\n\t\t  </child>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">False</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button2\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Load a config file</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Load</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-open</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_load_clicked\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button3\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Save a config file</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Save</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-save</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_save_activate\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolItem\" id=\"toolitem2\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkVSeparator\" id=\"vseparator2\">\n\t\t      <property name=\"visible\">True</property>\n\t\t    </widget>\n\t\t  </child>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">False</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button4\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Single view</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Single</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-missing-image</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_single_clicked\" last_modification_time=\"Sun, 12 Jan 2003 14:28:39 GMT\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button5\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Split view</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Split</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-missing-image</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_split_clicked\" last_modification_time=\"Sun, 12 Jan 2003 14:28:45 GMT\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button6\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Full view</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Full</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-missing-image</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_full_clicked\" last_modification_time=\"Sun, 12 Jan 2003 14:28:50 GMT\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolItem\" id=\"toolitem3\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkVSeparator\" id=\"vseparator3\">\n\t\t      <property name=\"visible\">True</property>\n\t\t    </widget>\n\t\t  </child>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">False</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button7\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Collapse the whole tree in the right frame</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Collapse</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-remove</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_collapse_clicked\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkToolButton\" id=\"button8\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"tooltip\" translatable=\"yes\">Expand the whole tree in the right frame</property>\n\t\t  <property name=\"label\" translatable=\"yes\">Expand</property>\n\t\t  <property name=\"use_underline\">True</property>\n\t\t  <property name=\"stock_id\">gtk-add</property>\n\t\t  <property name=\"visible_horizontal\">True</property>\n\t\t  <property name=\"visible_vertical\">True</property>\n\t\t  <property name=\"is_important\">False</property>\n\t\t  <signal name=\"clicked\" handler=\"on_expand_clicked\"/>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"expand\">False</property>\n\t\t  <property name=\"homogeneous\">True</property>\n\t\t</packing>\n\t      </child>\n\t    </widget>\n\t  </child>\n\t</widget>\n\t<packing>\n\t  <property name=\"padding\">0</property>\n\t  <property name=\"expand\">False</property>\n\t  <property name=\"fill\">False</property>\n\t</packing>\n      </child>\n\n      <child>\n\t<widget class=\"GtkHPaned\" id=\"hpaned1\">\n\t  <property name=\"width_request\">1</property>\n\t  <property name=\"visible\">True</property>\n\t  <property name=\"can_focus\">True</property>\n\t  <property name=\"position\">0</property>\n\n\t  <child>\n\t    <widget class=\"GtkScrolledWindow\" id=\"scrolledwindow1\">\n\t      <property name=\"visible\">True</property>\n\t      <property name=\"hscrollbar_policy\">GTK_POLICY_AUTOMATIC</property>\n\t      <property name=\"vscrollbar_policy\">GTK_POLICY_AUTOMATIC</property>\n\t      <property name=\"shadow_type\">GTK_SHADOW_IN</property>\n\t      <property name=\"window_placement\">GTK_CORNER_TOP_LEFT</property>\n\n\t      <child>\n\t\t<widget class=\"GtkTreeView\" id=\"treeview1\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"can_focus\">True</property>\n\t\t  <property name=\"headers_visible\">True</property>\n\t\t  <property name=\"rules_hint\">False</property>\n\t\t  <property name=\"reorderable\">False</property>\n\t\t  <property name=\"enable_search\">False</property>\n\t\t  <signal name=\"cursor_changed\" handler=\"on_treeview2_cursor_changed\" last_modification_time=\"Sun, 12 Jan 2003 15:58:22 GMT\"/>\n\t\t  <signal name=\"button_press_event\" handler=\"on_treeview1_button_press_event\" last_modification_time=\"Sun, 12 Jan 2003 16:03:52 GMT\"/>\n\t\t  <signal name=\"key_press_event\" handler=\"on_treeview2_key_press_event\" last_modification_time=\"Sun, 12 Jan 2003 16:11:44 GMT\"/>\n\t\t</widget>\n\t      </child>\n\t    </widget>\n\t    <packing>\n\t      <property name=\"shrink\">True</property>\n\t      <property name=\"resize\">False</property>\n\t    </packing>\n\t  </child>\n\n\t  <child>\n\t    <widget class=\"GtkVPaned\" id=\"vpaned1\">\n\t      <property name=\"visible\">True</property>\n\t      <property name=\"can_focus\">True</property>\n\t      <property name=\"position\">0</property>\n\n\t      <child>\n\t\t<widget class=\"GtkScrolledWindow\" id=\"scrolledwindow2\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"hscrollbar_policy\">GTK_POLICY_AUTOMATIC</property>\n\t\t  <property name=\"vscrollbar_policy\">GTK_POLICY_AUTOMATIC</property>\n\t\t  <property name=\"shadow_type\">GTK_SHADOW_IN</property>\n\t\t  <property name=\"window_placement\">GTK_CORNER_TOP_LEFT</property>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkTreeView\" id=\"treeview2\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"can_focus\">True</property>\n\t\t      <property name=\"has_focus\">True</property>\n\t\t      <property name=\"headers_visible\">True</property>\n\t\t      <property name=\"rules_hint\">False</property>\n\t\t      <property name=\"reorderable\">False</property>\n\t\t      <property name=\"enable_search\">False</property>\n\t\t      <signal name=\"cursor_changed\" handler=\"on_treeview2_cursor_changed\" last_modification_time=\"Sun, 12 Jan 2003 15:57:55 GMT\"/>\n\t\t      <signal name=\"button_press_event\" handler=\"on_treeview2_button_press_event\" last_modification_time=\"Sun, 12 Jan 2003 15:57:58 GMT\"/>\n\t\t      <signal name=\"key_press_event\" handler=\"on_treeview2_key_press_event\" last_modification_time=\"Sun, 12 Jan 2003 15:58:01 GMT\"/>\n\t\t    </widget>\n\t\t  </child>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"shrink\">True</property>\n\t\t  <property name=\"resize\">False</property>\n\t\t</packing>\n\t      </child>\n\n\t      <child>\n\t\t<widget class=\"GtkScrolledWindow\" id=\"scrolledwindow3\">\n\t\t  <property name=\"visible\">True</property>\n\t\t  <property name=\"hscrollbar_policy\">GTK_POLICY_NEVER</property>\n\t\t  <property name=\"vscrollbar_policy\">GTK_POLICY_AUTOMATIC</property>\n\t\t  <property name=\"shadow_type\">GTK_SHADOW_IN</property>\n\t\t  <property name=\"window_placement\">GTK_CORNER_TOP_LEFT</property>\n\n\t\t  <child>\n\t\t    <widget class=\"GtkTextView\" id=\"textview3\">\n\t\t      <property name=\"visible\">True</property>\n\t\t      <property name=\"can_focus\">True</property>\n\t\t      <property name=\"editable\">False</property>\n\t\t      <property name=\"overwrite\">False</property>\n\t\t      <property name=\"accepts_tab\">True</property>\n\t\t      <property name=\"justification\">GTK_JUSTIFY_LEFT</property>\n\t\t      <property name=\"wrap_mode\">GTK_WRAP_WORD</property>\n\t\t      <property name=\"cursor_visible\">True</property>\n\t\t      <property name=\"pixels_above_lines\">0</property>\n\t\t      <property name=\"pixels_below_lines\">0</property>\n\t\t      <property name=\"pixels_inside_wrap\">0</property>\n\t\t      <property name=\"left_margin\">0</property>\n\t\t      <property name=\"right_margin\">0</property>\n\t\t      <property name=\"indent\">0</property>\n\t\t      <property name=\"text\" translatable=\"yes\">Sorry, no help available for this option yet.</property>\n\t\t    </widget>\n\t\t  </child>\n\t\t</widget>\n\t\t<packing>\n\t\t  <property name=\"shrink\">True</property>\n\t\t  <property name=\"resize\">True</property>\n\t\t</packing>\n\t      </child>\n\t    </widget>\n\t    <packing>\n\t      <property name=\"shrink\">True</property>\n\t      <property name=\"resize\">True</property>\n\t    </packing>\n\t  </child>\n\t</widget>\n\t<packing>\n\t  <property name=\"padding\">0</property>\n\t  <property name=\"expand\">True</property>\n\t  <property name=\"fill\">True</property>\n\t</packing>\n      </child>\n    </widget>\n  </child>\n</widget>\n\n</glade-interface>\n"
  },
  {
    "path": "kconfig/images.c",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\nstatic const char *xpm_load[] = {\n\"22 22 5 1\",\n\". c None\",\n\"# c #000000\",\n\"c c #838100\",\n\"a c #ffff00\",\n\"b c #ffffff\",\n\"......................\",\n\"......................\",\n\"......................\",\n\"............####....#.\",\n\"...........#....##.##.\",\n\"..................###.\",\n\".................####.\",\n\".####...........#####.\",\n\"#abab##########.......\",\n\"#babababababab#.......\",\n\"#ababababababa#.......\",\n\"#babababababab#.......\",\n\"#ababab###############\",\n\"#babab##cccccccccccc##\",\n\"#abab##cccccccccccc##.\",\n\"#bab##cccccccccccc##..\",\n\"#ab##cccccccccccc##...\",\n\"#b##cccccccccccc##....\",\n\"###cccccccccccc##.....\",\n\"##cccccccccccc##......\",\n\"###############.......\",\n\"......................\"};\n\nstatic const char *xpm_save[] = {\n\"22 22 5 1\",\n\". c None\",\n\"# c #000000\",\n\"a c #838100\",\n\"b c #c5c2c5\",\n\"c c #cdb6d5\",\n\"......................\",\n\".####################.\",\n\".#aa#bbbbbbbbbbbb#bb#.\",\n\".#aa#bbbbbbbbbbbb#bb#.\",\n\".#aa#bbbbbbbbbcbb####.\",\n\".#aa#bbbccbbbbbbb#aa#.\",\n\".#aa#bbbccbbbbbbb#aa#.\",\n\".#aa#bbbbbbbbbbbb#aa#.\",\n\".#aa#bbbbbbbbbbbb#aa#.\",\n\".#aa#bbbbbbbbbbbb#aa#.\",\n\".#aa#bbbbbbbbbbbb#aa#.\",\n\".#aaa############aaa#.\",\n\".#aaaaaaaaaaaaaaaaaa#.\",\n\".#aaaaaaaaaaaaaaaaaa#.\",\n\".#aaa#############aa#.\",\n\".#aaa#########bbb#aa#.\",\n\".#aaa#########bbb#aa#.\",\n\".#aaa#########bbb#aa#.\",\n\".#aaa#########bbb#aa#.\",\n\".#aaa#########bbb#aa#.\",\n\"..##################..\",\n\"......................\"};\n\nstatic const char *xpm_back[] = {\n\"22 22 3 1\",\n\". c None\",\n\"# c #000083\",\n\"a c #838183\",\n\"......................\",\n\"......................\",\n\"......................\",\n\"......................\",\n\"......................\",\n\"...........######a....\",\n\"..#......##########...\",\n\"..##...####......##a..\",\n\"..###.###.........##..\",\n\"..######..........##..\",\n\"..#####...........##..\",\n\"..######..........##..\",\n\"..#######.........##..\",\n\"..########.......##a..\",\n\"...............a###...\",\n\"...............###....\",\n\"......................\",\n\"......................\",\n\"......................\",\n\"......................\",\n\"......................\",\n\"......................\"};\n\nstatic const char *xpm_tree_view[] = {\n\"22 22 2 1\",\n\". c None\",\n\"# c #000000\",\n\"......................\",\n\"......................\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......########........\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......########........\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......#...............\",\n\"......########........\",\n\"......................\",\n\"......................\"};\n\nstatic const char *xpm_single_view[] = {\n\"22 22 2 1\",\n\". c None\",\n\"# c #000000\",\n\"......................\",\n\"......................\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"..........#...........\",\n\"......................\",\n\"......................\"};\n\nstatic const char *xpm_split_view[] = {\n\"22 22 2 1\",\n\". c None\",\n\"# c #000000\",\n\"......................\",\n\"......................\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......#......#........\",\n\"......................\",\n\"......................\"};\n\nstatic const char *xpm_symbol_no[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\" .......... \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\" .......... \",\n\"            \"};\n\nstatic const char *xpm_symbol_mod[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\" .......... \",\n\" .        . \",\n\" .        . \",\n\" .   ..   . \",\n\" .  ....  . \",\n\" .  ....  . \",\n\" .   ..   . \",\n\" .        . \",\n\" .        . \",\n\" .......... \",\n\"            \"};\n\nstatic const char *xpm_symbol_yes[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\" .......... \",\n\" .        . \",\n\" .        . \",\n\" .      . . \",\n\" .     .. . \",\n\" . .  ..  . \",\n\" . ....   . \",\n\" .  ..    . \",\n\" .        . \",\n\" .......... \",\n\"            \"};\n\nstatic const char *xpm_choice_no[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\"    ....    \",\n\"  ..    ..  \",\n\"  .      .  \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\" .        . \",\n\"  .      .  \",\n\"  ..    ..  \",\n\"    ....    \",\n\"            \"};\n\nstatic const char *xpm_choice_yes[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\"    ....    \",\n\"  ..    ..  \",\n\"  .      .  \",\n\" .   ..   . \",\n\" .  ....  . \",\n\" .  ....  . \",\n\" .   ..   . \",\n\"  .      .  \",\n\"  ..    ..  \",\n\"    ....    \",\n\"            \"};\n\nstatic const char *xpm_menu[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\" .......... \",\n\" .        . \",\n\" . ..     . \",\n\" . ....   . \",\n\" . ...... . \",\n\" . ...... . \",\n\" . ....   . \",\n\" . ..     . \",\n\" .        . \",\n\" .......... \",\n\"            \"};\n\nstatic const char *xpm_menu_inv[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\" .......... \",\n\" .......... \",\n\" ..  ...... \",\n\" ..    .... \",\n\" ..      .. \",\n\" ..      .. \",\n\" ..    .... \",\n\" ..  ...... \",\n\" .......... \",\n\" .......... \",\n\"            \"};\n\nstatic const char *xpm_menuback[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\" .......... \",\n\" .        . \",\n\" .     .. . \",\n\" .   .... . \",\n\" . ...... . \",\n\" . ...... . \",\n\" .   .... . \",\n\" .     .. . \",\n\" .        . \",\n\" .......... \",\n\"            \"};\n\nstatic const char *xpm_void[] = {\n\"12 12 2 1\",\n\"  c white\",\n\". c black\",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \",\n\"            \"};\n"
  },
  {
    "path": "kconfig/kxgettext.c",
    "content": "/*\n * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005\n *\n * Released under the terms of the GNU GPL v2.0\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"lkc.h\"\n\nstatic char *escape(const char* text, char *bf, int len)\n{\n\tchar *bfp = bf;\n\tint multiline = strchr(text, '\\n') != NULL;\n\tint eol = 0;\n\tint textlen = strlen(text);\n\n\tif ((textlen > 0) && (text[textlen-1] == '\\n'))\n\t\teol = 1;\n\n\t*bfp++ = '\"';\n\t--len;\n\n\tif (multiline) {\n\t\t*bfp++ = '\"';\n\t\t*bfp++ = '\\n';\n\t\t*bfp++ = '\"';\n\t\tlen -= 3;\n\t}\n\n\twhile (*text != '\\0' && len > 1) {\n\t\tif (*text == '\"')\n\t\t\t*bfp++ = '\\\\';\n\t\telse if (*text == '\\n') {\n\t\t\t*bfp++ = '\\\\';\n\t\t\t*bfp++ = 'n';\n\t\t\t*bfp++ = '\"';\n\t\t\t*bfp++ = '\\n';\n\t\t\t*bfp++ = '\"';\n\t\t\tlen -= 5;\n\t\t\t++text;\n\t\t\tgoto next;\n\t\t}\n\t\telse if (*text == '\\\\') {\n\t\t\t*bfp++ = '\\\\';\n\t\t\tlen--;\n\t\t}\n\t\t*bfp++ = *text++;\nnext:\n\t\t--len;\n\t}\n\n\tif (multiline && eol)\n\t\tbfp -= 3;\n\n\t*bfp++ = '\"';\n\t*bfp = '\\0';\n\n\treturn bf;\n}\n\nstruct file_line {\n\tstruct file_line *next;\n\tconst char *file;\n\tint lineno;\n};\n\nstatic struct file_line *file_line__new(const char *file, int lineno)\n{\n\tstruct file_line *self = malloc(sizeof(*self));\n\n\tif (self == NULL)\n\t\tgoto out;\n\n\tself->file   = file;\n\tself->lineno = lineno;\n\tself->next   = NULL;\nout:\n\treturn self;\n}\n\nstruct message {\n\tconst char\t *msg;\n\tconst char\t *option;\n\tstruct message\t *next;\n\tstruct file_line *files;\n};\n\nstatic struct message *message__list;\n\nstatic struct message *message__new(const char *msg, char *option,\n\t\t\t\t    const char *file, int lineno)\n{\n\tstruct message *self = malloc(sizeof(*self));\n\n\tif (self == NULL)\n\t\tgoto out;\n\n\tself->files = file_line__new(file, lineno);\n\tif (self->files == NULL)\n\t\tgoto out_fail;\n\n\tself->msg = strdup(msg);\n\tif (self->msg == NULL)\n\t\tgoto out_fail_msg;\n\n\tself->option = option;\n\tself->next = NULL;\nout:\n\treturn self;\nout_fail_msg:\n\tfree(self->files);\nout_fail:\n\tfree(self);\n\tself = NULL;\n\tgoto out;\n}\n\nstatic struct message *mesage__find(const char *msg)\n{\n\tstruct message *m = message__list;\n\n\twhile (m != NULL) {\n\t\tif (strcmp(m->msg, msg) == 0)\n\t\t\tbreak;\n\t\tm = m->next;\n\t}\n\n\treturn m;\n}\n\nstatic int message__add_file_line(struct message *self, const char *file,\n\t\t\t\t  int lineno)\n{\n\tint rc = -1;\n\tstruct file_line *fl = file_line__new(file, lineno);\n\n\tif (fl == NULL)\n\t\tgoto out;\n\n\tfl->next    = self->files;\n\tself->files = fl;\n\trc = 0;\nout:\n\treturn rc;\n}\n\nstatic int message__add(const char *msg, char *option, const char *file,\n\t\t\tint lineno)\n{\n\tint rc = 0;\n\tchar bf[16384];\n\tchar *escaped = escape(msg, bf, sizeof(bf));\n\tstruct message *m = mesage__find(escaped);\n\n\tif (m != NULL)\n\t\trc = message__add_file_line(m, file, lineno);\n\telse {\n\t\tm = message__new(escaped, option, file, lineno);\n\n\t\tif (m != NULL) {\n\t\t\tm->next\t      = message__list;\n\t\t\tmessage__list = m;\n\t\t} else\n\t\t\trc = -1;\n\t}\n\treturn rc;\n}\n\nstatic void menu_build_message_list(struct menu *menu)\n{\n\tstruct menu *child;\n\n\tmessage__add(menu_get_prompt(menu), NULL,\n\t\t     menu->file == NULL ? \"Root Menu\" : menu->file->name,\n\t\t     menu->lineno);\n\n\tif (menu->sym != NULL && menu_has_help(menu))\n\t\tmessage__add(menu_get_help(menu), menu->sym->name,\n\t\t\t     menu->file == NULL ? \"Root Menu\" : menu->file->name,\n\t\t\t     menu->lineno);\n\n\tfor (child = menu->list; child != NULL; child = child->next)\n\t\tif (child->prompt != NULL)\n\t\t\tmenu_build_message_list(child);\n}\n\nstatic void message__print_file_lineno(struct message *self)\n{\n\tstruct file_line *fl = self->files;\n\n\tputchar('\\n');\n\tif (self->option != NULL)\n\t\tprintf(\"# %s:00000\\n\", self->option);\n\n\tprintf(\"#: %s:%d\", fl->file, fl->lineno);\n\tfl = fl->next;\n\n\twhile (fl != NULL) {\n\t\tprintf(\", %s:%d\", fl->file, fl->lineno);\n\t\tfl = fl->next;\n\t}\n\n\tputchar('\\n');\n}\n\nstatic void message__print_gettext_msgid_msgstr(struct message *self)\n{\n\tmessage__print_file_lineno(self);\n\n\tprintf(\"msgid %s\\n\"\n\t       \"msgstr \\\"\\\"\\n\", self->msg);\n}\n\nstatic void menu__xgettext(void)\n{\n\tstruct message *m = message__list;\n\n\twhile (m != NULL) {\n\t\t/* skip empty lines (\"\") */\n\t\tif (strlen(m->msg) > sizeof(\"\\\"\\\"\"))\n\t\t\tmessage__print_gettext_msgid_msgstr(m);\n\t\tm = m->next;\n\t}\n}\n\nint main(int ac, char **av)\n{\n\tconf_parse(av[1]);\n\n\tmenu_build_message_list(menu_get_root_menu(NULL));\n\tmenu__xgettext();\n\treturn 0;\n}\n"
  },
  {
    "path": "kconfig/list.h",
    "content": "#ifndef LIST_H\n#define LIST_H\n\n/*\n * Copied from include/linux/...\n */\n\n#undef offsetof\n#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)\n\n/**\n * container_of - cast a member of a structure out to the containing structure\n * @ptr:        the pointer to the member.\n * @type:       the type of the container struct this is embedded in.\n * @member:     the name of the member within the struct.\n *\n */\n#define container_of(ptr, type, member) ({                      \\\n\tconst typeof( ((type *)0)->member ) *__mptr = (ptr);    \\\n\t(type *)( (char *)__mptr - offsetof(type,member) );})\n\n\nstruct list_head {\n\tstruct list_head *next, *prev;\n};\n\n\n#define LIST_HEAD_INIT(name) { &(name), &(name) }\n\n#define LIST_HEAD(name) \\\n\tstruct list_head name = LIST_HEAD_INIT(name)\n\n/**\n * list_entry - get the struct for this entry\n * @ptr:\tthe &struct list_head pointer.\n * @type:\tthe type of the struct this is embedded in.\n * @member:\tthe name of the list_struct within the struct.\n */\n#define list_entry(ptr, type, member) \\\n\tcontainer_of(ptr, type, member)\n\n/**\n * list_for_each_entry\t-\titerate over list of given type\n * @pos:\tthe type * to use as a loop cursor.\n * @head:\tthe head for your list.\n * @member:\tthe name of the list_struct within the struct.\n */\n#define list_for_each_entry(pos, head, member)\t\t\t\t\\\n\tfor (pos = list_entry((head)->next, typeof(*pos), member);\t\\\n\t     &pos->member != (head); \t\\\n\t     pos = list_entry(pos->member.next, typeof(*pos), member))\n\n/**\n * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry\n * @pos:\tthe type * to use as a loop cursor.\n * @n:\t\tanother type * to use as temporary storage\n * @head:\tthe head for your list.\n * @member:\tthe name of the list_struct within the struct.\n */\n#define list_for_each_entry_safe(pos, n, head, member)\t\t\t\\\n\tfor (pos = list_entry((head)->next, typeof(*pos), member),\t\\\n\t\tn = list_entry(pos->member.next, typeof(*pos), member);\t\\\n\t     &pos->member != (head);\t\t\t\t\t\\\n\t     pos = n, n = list_entry(n->member.next, typeof(*n), member))\n\n/**\n * list_empty - tests whether a list is empty\n * @head: the list to test.\n */\nstatic inline int list_empty(const struct list_head *head)\n{\n\treturn head->next == head;\n}\n\n/*\n * Insert a new entry between two known consecutive entries.\n *\n * This is only for internal list manipulation where we know\n * the prev/next entries already!\n */\nstatic inline void __list_add(struct list_head *_new,\n\t\t\t      struct list_head *prev,\n\t\t\t      struct list_head *next)\n{\n\tnext->prev = _new;\n\t_new->next = next;\n\t_new->prev = prev;\n\tprev->next = _new;\n}\n\n/**\n * list_add_tail - add a new entry\n * @new: new entry to be added\n * @head: list head to add it before\n *\n * Insert a new entry before the specified head.\n * This is useful for implementing queues.\n */\nstatic inline void list_add_tail(struct list_head *_new, struct list_head *head)\n{\n\t__list_add(_new, head->prev, head);\n}\n\n/*\n * Delete a list entry by making the prev/next entries\n * point to each other.\n *\n * This is only for internal list manipulation where we know\n * the prev/next entries already!\n */\nstatic inline void __list_del(struct list_head *prev, struct list_head *next)\n{\n\tnext->prev = prev;\n\tprev->next = next;\n}\n\n#define LIST_POISON1  ((void *) 0x00100100)\n#define LIST_POISON2  ((void *) 0x00200200)\n/**\n * list_del - deletes entry from list.\n * @entry: the element to delete from the list.\n * Note: list_empty() on entry does not return true after this, the entry is\n * in an undefined state.\n */\nstatic inline void list_del(struct list_head *entry)\n{\n\t__list_del(entry->prev, entry->next);\n\tentry->next = (struct list_head*)LIST_POISON1;\n\tentry->prev = (struct list_head*)LIST_POISON2;\n}\n#endif\n"
  },
  {
    "path": "kconfig/lkc.h",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#ifndef LKC_H\n#define LKC_H\n\n#include \"expr.h\"\n\n#ifndef KBUILD_NO_NLS\n# include <libintl.h>\n#else\nstatic inline const char *gettext(const char *txt) { return txt; }\nstatic inline void textdomain(const char *domainname) {}\nstatic inline void bindtextdomain(const char *name, const char *dir) {}\nstatic inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define P(name,type,arg)\textern type name arg\n#include \"lkc_proto.h\"\n#undef P\n\n#define SRCTREE \"srctree\"\n\n#ifndef PACKAGE\n#define PACKAGE \"linux\"\n#endif\n\n#define LOCALEDIR \"/usr/share/locale\"\n\n#define _(text) gettext(text)\n#define N_(text) (text)\n\n#ifndef CONFIG_\n#define CONFIG_ \"CONFIG_\"\n#endif\nstatic inline const char *CONFIG_prefix(void)\n{\n\treturn getenv( \"CONFIG_\" ) ?: CONFIG_;\n}\n#undef CONFIG_\n#define CONFIG_ CONFIG_prefix()\n\n#define TF_COMMAND\t0x0001\n#define TF_PARAM\t0x0002\n#define TF_OPTION\t0x0004\n\nenum conf_def_mode {\n\tdef_default,\n\tdef_yes,\n\tdef_mod,\n\tdef_no,\n\tdef_random\n};\n\n#define T_OPT_MODULES\t\t1\n#define T_OPT_DEFCONFIG_LIST\t2\n#define T_OPT_ENV\t\t3\n#define T_OPT_ALLNOCONFIG_Y\t4\n\nstruct kconf_id {\n\tint name;\n\tint token;\n\tunsigned int flags;\n\tenum symbol_type stype;\n};\n\nextern int zconfdebug;\n\nint zconfparse(void);\nvoid zconfdump(FILE *out);\nvoid zconf_starthelp(void);\nFILE *zconf_fopen(const char *name);\nvoid zconf_initscan(const char *name);\nvoid zconf_nextfile(const char *name);\nint zconf_lineno(void);\nconst char *zconf_curname(void);\n\n/* confdata.c */\nconst char *conf_get_configname(void);\nconst char *conf_get_autoconfig_name(void);\nchar *conf_get_default_confname(void);\nvoid sym_set_change_count(int count);\nvoid sym_add_change_count(int count);\nbool conf_set_all_new_symbols(enum conf_def_mode mode);\nvoid set_all_choice_values(struct symbol *csym);\n\nstruct conf_printer {\n\tvoid (*print_symbol)(FILE *, struct symbol *, const char *, void *);\n\tvoid (*print_comment)(FILE *, const char *, void *);\n};\n\n/* confdata.c and expr.c */\nstatic inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)\n{\n\tassert(len != 0);\n\n\tif (fwrite(str, len, count, out) != count)\n\t\tfprintf(stderr, \"Error in writing or end of file.\\n\");\n}\n\n/* menu.c */\nvoid _menu_init(void);\nvoid menu_warn(struct menu *menu, const char *fmt, ...);\nstruct menu *menu_add_menu(void);\nvoid menu_end_menu(void);\nvoid menu_add_entry(struct symbol *sym);\nvoid menu_end_entry(void);\nvoid menu_add_dep(struct expr *dep);\nvoid menu_add_visibility(struct expr *dep);\nstruct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);\nstruct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);\nvoid menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);\nvoid menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);\nvoid menu_add_option(int token, char *arg);\nvoid menu_finalize(struct menu *parent);\nvoid menu_set_type(int type);\n\n/* util.c */\nstruct file *file_lookup(const char *name);\nint file_write_dep(const char *name);\nvoid *xmalloc(size_t size);\nvoid *xcalloc(size_t nmemb, size_t size);\n\nstruct gstr {\n\tsize_t len;\n\tchar  *s;\n\t/*\n\t* when max_width is not zero long lines in string s (if any) get\n\t* wrapped not to exceed the max_width value\n\t*/\n\tint max_width;\n};\nstruct gstr str_new(void);\nstruct gstr str_assign(const char *s);\nvoid str_free(struct gstr *gs);\nvoid str_append(struct gstr *gs, const char *s);\nvoid str_printf(struct gstr *gs, const char *fmt, ...);\nconst char *str_get(struct gstr *gs);\n\n/* symbol.c */\nextern struct expr *sym_env_list;\n\nvoid sym_init(void);\nvoid sym_clear_all_valid(void);\nvoid sym_set_all_changed(void);\nvoid sym_set_changed(struct symbol *sym);\nstruct symbol *sym_choice_default(struct symbol *sym);\nconst char *sym_get_string_default(struct symbol *sym);\nstruct symbol *sym_check_deps(struct symbol *sym);\nstruct property *prop_alloc(enum prop_type type, struct symbol *sym);\nstruct symbol *prop_get_symbol(struct property *prop);\nstruct property *sym_get_env_prop(struct symbol *sym);\n\nstatic inline tristate sym_get_tristate_value(struct symbol *sym)\n{\n\treturn sym->curr.tri;\n}\n\n\nstatic inline struct symbol *sym_get_choice_value(struct symbol *sym)\n{\n\treturn (struct symbol *)sym->curr.val;\n}\n\nstatic inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)\n{\n\treturn sym_set_tristate_value(chval, yes);\n}\n\nstatic inline bool sym_is_choice(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_CHOICE ? true : false;\n}\n\nstatic inline bool sym_is_choice_value(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_CHOICEVAL ? true : false;\n}\n\nstatic inline bool sym_is_optional(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_OPTIONAL ? true : false;\n}\n\nstatic inline bool sym_has_value(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_DEF_USER ? true : false;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* LKC_H */\n"
  },
  {
    "path": "kconfig/lkc_proto.h",
    "content": "#include <stdarg.h>\n\n/* confdata.c */\nP(conf_parse,void,(const char *name));\nP(conf_read,int,(const char *name));\nP(conf_read_simple,int,(const char *name, int));\nP(conf_write_defconfig,int,(const char *name));\nP(conf_write,int,(const char *name));\nP(conf_write_autoconf,int,(void));\nP(conf_get_changed,bool,(void));\nP(conf_set_changed_callback, void,(void (*fn)(void)));\nP(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap)));\n\n/* menu.c */\nP(rootmenu,struct menu,);\n\nP(menu_is_empty, bool, (struct menu *menu));\nP(menu_is_visible, bool, (struct menu *menu));\nP(menu_has_prompt, bool, (struct menu *menu));\nP(menu_get_prompt,const char *,(struct menu *menu));\nP(menu_get_root_menu,struct menu *,(struct menu *menu));\nP(menu_get_parent_menu,struct menu *,(struct menu *menu));\nP(menu_has_help,bool,(struct menu *menu));\nP(menu_get_help,const char *,(struct menu *menu));\nP(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head\n\t\t\t *head));\nP(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head\n\t\t\t\t   *head));\nP(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));\n\n/* symbol.c */\nP(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);\n\nP(sym_lookup,struct symbol *,(const char *name, int flags));\nP(sym_find,struct symbol *,(const char *name));\nP(sym_expand_string_value,const char *,(const char *in));\nP(sym_escape_string_value, const char *,(const char *in));\nP(sym_re_search,struct symbol **,(const char *pattern));\nP(sym_type_name,const char *,(enum symbol_type type));\nP(sym_calc_value,void,(struct symbol *sym));\nP(sym_get_type,enum symbol_type,(struct symbol *sym));\nP(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));\nP(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));\nP(sym_toggle_tristate_value,tristate,(struct symbol *sym));\nP(sym_string_valid,bool,(struct symbol *sym, const char *newval));\nP(sym_string_within_range,bool,(struct symbol *sym, const char *str));\nP(sym_set_string_value,bool,(struct symbol *sym, const char *newval));\nP(sym_is_changable,bool,(struct symbol *sym));\nP(sym_get_choice_prop,struct property *,(struct symbol *sym));\nP(sym_get_default_prop,struct property *,(struct symbol *sym));\nP(sym_get_string_value,const char *,(struct symbol *sym));\n\nP(prop_get_type_name,const char *,(enum prop_type type));\n\n/* expr.c */\nP(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));\nP(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken));\n"
  },
  {
    "path": "kconfig/lpc17xx.cfg",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Platform Selection\n#\n# ARCH_LM3S is not set\nARCH_LPC17XX=y\n# ARCH_STM32F4 is not set\n# ARCH_LPC1763 is not set\n# ARCH_LPC1764 is not set\n# ARCH_LPC1765 is not set\n# ARCH_LPC1766 is not set\n# ARCH_LPC1767 is not set\nARCH_LPC1768=y\n# ARCH_LPC1769 is not set\nFLASH_SIZE_512KB=y\nRAM_SIZE_32KB=y\nCLK_100MHZ=y\nMACH_LPC1768MBED=y\n# MACH_SEEEDPRO is not set\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=48\nKRAMMEM_SIZE=6\n\n#\n# Subsystems\n#\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\n\n#\n# Sockets\n#\nSOCK_UNIX=y\n\n#\n# Devices\n#\nDEVNULL=y\n# DEVUART is not set\nDEVGPIO=y\n\n#\n# Applications\n#\nFRESH=y\n# TASK2 is not set\n# PRODCONS is not set\n"
  },
  {
    "path": "kconfig/mconf.c",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n *\n * Introduced single menu mode (show all sub-menus in one large tree).\n * 2002-11-06 Petr Baudis <pasky@ucw.cz>\n *\n * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>\n */\n\n#include <ctype.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <signal.h>\n#include <unistd.h>\n#include <locale.h>\n\n#include \"lkc.h\"\n#include \"lxdialog/dialog.h\"\n\nstatic const char mconf_readme[] = N_(\n\"Overview\\n\"\n\"--------\\n\"\n\"This interface lets you select features and parameters for the build.\\n\"\n\"Features can either be built-in, modularized, or ignored. Parameters\\n\"\n\"must be entered in as decimal or hexadecimal numbers or text.\\n\"\n\"\\n\"\n\"Menu items beginning with following braces represent features that\\n\"\n\"  [ ] can be built in or removed\\n\"\n\"  < > can be built in, modularized or removed\\n\"\n\"  { } can be built in or modularized (selected by other feature)\\n\"\n\"  - - are selected by other feature,\\n\"\n\"while *, M or whitespace inside braces means to build in, build as\\n\"\n\"a module or to exclude the feature respectively.\\n\"\n\"\\n\"\n\"To change any of these features, highlight it with the cursor\\n\"\n\"keys and press <Y> to build it in, <M> to make it a module or\\n\"\n\"<N> to remove it.  You may also press the <Space Bar> to cycle\\n\"\n\"through the available options (i.e. Y->N->M->Y).\\n\"\n\"\\n\"\n\"Some additional keyboard hints:\\n\"\n\"\\n\"\n\"Menus\\n\"\n\"----------\\n\"\n\"o  Use the Up/Down arrow keys (cursor keys) to highlight the item you\\n\"\n\"   wish to change or the submenu you wish to select and press <Enter>.\\n\"\n\"   Submenus are designated by \\\"--->\\\", empty ones by \\\"----\\\".\\n\"\n\"\\n\"\n\"   Shortcut: Press the option's highlighted letter (hotkey).\\n\"\n\"             Pressing a hotkey more than once will sequence\\n\"\n\"             through all visible items which use that hotkey.\\n\"\n\"\\n\"\n\"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\\n\"\n\"   unseen options into view.\\n\"\n\"\\n\"\n\"o  To exit a menu use the cursor keys to highlight the <Exit> button\\n\"\n\"   and press <ENTER>.\\n\"\n\"\\n\"\n\"   Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\\n\"\n\"             using those letters.  You may press a single <ESC>, but\\n\"\n\"             there is a delayed response which you may find annoying.\\n\"\n\"\\n\"\n\"   Also, the <TAB> and cursor keys will cycle between <Select>,\\n\"\n\"   <Exit>, <Help>, <Save>, and <Load>.\\n\"\n\"\\n\"\n\"o  To get help with an item, use the cursor keys to highlight <Help>\\n\"\n\"   and press <ENTER>.\\n\"\n\"\\n\"\n\"   Shortcut: Press <H> or <?>.\\n\"\n\"\\n\"\n\"o  To toggle the display of hidden options, press <Z>.\\n\"\n\"\\n\"\n\"\\n\"\n\"Radiolists  (Choice lists)\\n\"\n\"-----------\\n\"\n\"o  Use the cursor keys to select the option you wish to set and press\\n\"\n\"   <S> or the <SPACE BAR>.\\n\"\n\"\\n\"\n\"   Shortcut: Press the first letter of the option you wish to set then\\n\"\n\"             press <S> or <SPACE BAR>.\\n\"\n\"\\n\"\n\"o  To see available help for the item, use the cursor keys to highlight\\n\"\n\"   <Help> and Press <ENTER>.\\n\"\n\"\\n\"\n\"   Shortcut: Press <H> or <?>.\\n\"\n\"\\n\"\n\"   Also, the <TAB> and cursor keys will cycle between <Select> and\\n\"\n\"   <Help>\\n\"\n\"\\n\"\n\"\\n\"\n\"Data Entry\\n\"\n\"-----------\\n\"\n\"o  Enter the requested information and press <ENTER>\\n\"\n\"   If you are entering hexadecimal values, it is not necessary to\\n\"\n\"   add the '0x' prefix to the entry.\\n\"\n\"\\n\"\n\"o  For help, use the <TAB> or cursor keys to highlight the help option\\n\"\n\"   and press <ENTER>.  You can try <TAB><H> as well.\\n\"\n\"\\n\"\n\"\\n\"\n\"Text Box    (Help Window)\\n\"\n\"--------\\n\"\n\"o  Use the cursor keys to scroll up/down/left/right.  The VI editor\\n\"\n\"   keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\\n\"\n\"   those who are familiar with less and lynx.\\n\"\n\"\\n\"\n\"o  Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\\n\"\n\"\\n\"\n\"\\n\"\n\"Alternate Configuration Files\\n\"\n\"-----------------------------\\n\"\n\"Menuconfig supports the use of alternate configuration files for\\n\"\n\"those who, for various reasons, find it necessary to switch\\n\"\n\"between different configurations.\\n\"\n\"\\n\"\n\"The <Save> button will let you save the current configuration to\\n\"\n\"a file of your choosing.  Use the <Load> button to load a previously\\n\"\n\"saved alternate configuration.\\n\"\n\"\\n\"\n\"Even if you don't use alternate configuration files, but you find\\n\"\n\"during a Menuconfig session that you have completely messed up your\\n\"\n\"settings, you may use the <Load> button to restore your previously\\n\"\n\"saved settings from \\\".config\\\" without restarting Menuconfig.\\n\"\n\"\\n\"\n\"Other information\\n\"\n\"-----------------\\n\"\n\"If you use Menuconfig in an XTERM window, make sure you have your\\n\"\n\"$TERM variable set to point to an xterm definition which supports\\n\"\n\"color.  Otherwise, Menuconfig will look rather bad.  Menuconfig will\\n\"\n\"not display correctly in an RXVT window because rxvt displays only one\\n\"\n\"intensity of color, bright.\\n\"\n\"\\n\"\n\"Menuconfig will display larger menus on screens or xterms which are\\n\"\n\"set to display more than the standard 25 row by 80 column geometry.\\n\"\n\"In order for this to work, the \\\"stty size\\\" command must be able to\\n\"\n\"display the screen's current row and column geometry.  I STRONGLY\\n\"\n\"RECOMMEND that you make sure you do NOT have the shell variables\\n\"\n\"LINES and COLUMNS exported into your environment.  Some distributions\\n\"\n\"export those variables via /etc/profile.  Some ncurses programs can\\n\"\n\"become confused when those variables (LINES & COLUMNS) don't reflect\\n\"\n\"the true screen size.\\n\"\n\"\\n\"\n\"Optional personality available\\n\"\n\"------------------------------\\n\"\n\"If you prefer to have all of the options listed in a single menu,\\n\"\n\"rather than the default multimenu hierarchy, run the menuconfig with\\n\"\n\"MENUCONFIG_MODE environment variable set to single_menu. Example:\\n\"\n\"\\n\"\n\"make MENUCONFIG_MODE=single_menu menuconfig\\n\"\n\"\\n\"\n\"<Enter> will then unroll the appropriate category, or enfold it if it\\n\"\n\"is already unrolled.\\n\"\n\"\\n\"\n\"Note that this mode can eventually be a little more CPU expensive\\n\"\n\"(especially with a larger number of unrolled categories) than the\\n\"\n\"default mode.\\n\"\n\"\\n\"\n\"Different color themes available\\n\"\n\"--------------------------------\\n\"\n\"It is possible to select different color themes using the variable\\n\"\n\"MENUCONFIG_COLOR. To select a theme use:\\n\"\n\"\\n\"\n\"make MENUCONFIG_COLOR=<theme> menuconfig\\n\"\n\"\\n\"\n\"Available themes are\\n\"\n\" mono       => selects colors suitable for monochrome displays\\n\"\n\" blackbg    => selects a color scheme with black background\\n\"\n\" classic    => theme with blue background. The classic look\\n\"\n\" bluetitle  => an LCD friendly version of classic. (default)\\n\"\n\"\\n\"),\nmenu_instructions[] = N_(\n\t\"Arrow keys navigate the menu.  \"\n\t\"<Enter> selects submenus ---> (or empty submenus ----).  \"\n\t\"Highlighted letters are hotkeys.  \"\n\t\"Pressing <Y> includes, <N> excludes, <M> modularizes features.  \"\n\t\"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  \"\n\t\"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable\"),\nradiolist_instructions[] = N_(\n\t\"Use the arrow keys to navigate this window or \"\n\t\"press the hotkey of the item you wish to select \"\n\t\"followed by the <SPACE BAR>. \"\n\t\"Press <?> for additional information about this option.\"),\ninputbox_instructions_int[] = N_(\n\t\"Please enter a decimal value. \"\n\t\"Fractions will not be accepted.  \"\n\t\"Use the <TAB> key to move from the input field to the buttons below it.\"),\ninputbox_instructions_hex[] = N_(\n\t\"Please enter a hexadecimal value. \"\n\t\"Use the <TAB> key to move from the input field to the buttons below it.\"),\ninputbox_instructions_string[] = N_(\n\t\"Please enter a string value. \"\n\t\"Use the <TAB> key to move from the input field to the buttons below it.\"),\nsetmod_text[] = N_(\n\t\"This feature depends on another which has been configured as a module.\\n\"\n\t\"As a result, this feature will be built as a module.\"),\nload_config_text[] = N_(\n\t\"Enter the name of the configuration file you wish to load.  \"\n\t\"Accept the name shown to restore the configuration you \"\n\t\"last retrieved.  Leave blank to abort.\"),\nload_config_help[] = N_(\n\t\"\\n\"\n\t\"For various reasons, one may wish to keep several different\\n\"\n\t\"configurations available on a single machine.\\n\"\n\t\"\\n\"\n\t\"If you have saved a previous configuration in a file other than the\\n\"\n\t\"default one, entering its name here will allow you to modify that\\n\"\n\t\"configuration.\\n\"\n\t\"\\n\"\n\t\"If you are uncertain, then you have probably never used alternate\\n\"\n\t\"configuration files. You should therefore leave this blank to abort.\\n\"),\nsave_config_text[] = N_(\n\t\"Enter a filename to which this configuration should be saved \"\n\t\"as an alternate.  Leave blank to abort.\"),\nsave_config_help[] = N_(\n\t\"\\n\"\n\t\"For various reasons, one may wish to keep different configurations\\n\"\n\t\"available on a single machine.\\n\"\n\t\"\\n\"\n\t\"Entering a file name here will allow you to later retrieve, modify\\n\"\n\t\"and use the current configuration as an alternate to whatever\\n\"\n\t\"configuration options you have selected at that time.\\n\"\n\t\"\\n\"\n\t\"If you are uncertain what all this means then you should probably\\n\"\n\t\"leave this blank.\\n\"),\nsearch_help[] = N_(\n\t\"\\n\"\n\t\"Search for symbols and display their relations.\\n\"\n\t\"Regular expressions are allowed.\\n\"\n\t\"Example: search for \\\"^FOO\\\"\\n\"\n\t\"Result:\\n\"\n\t\"-----------------------------------------------------------------\\n\"\n\t\"Symbol: FOO [=m]\\n\"\n\t\"Type  : tristate\\n\"\n\t\"Prompt: Foo bus is used to drive the bar HW\\n\"\n\t\"  Location:\\n\"\n\t\"    -> Bus options (PCI, PCMCIA, EISA, ISA)\\n\"\n\t\"      -> PCI support (PCI [=y])\\n\"\n\t\"(1)     -> PCI access mode (<choice> [=y])\\n\"\n\t\"  Defined at drivers/pci/Kconfig:47\\n\"\n\t\"  Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\\n\"\n\t\"  Selects: LIBCRC32\\n\"\n\t\"  Selected by: BAR [=n]\\n\"\n\t\"-----------------------------------------------------------------\\n\"\n\t\"o The line 'Type:' shows the type of the configuration option for\\n\"\n\t\"  this symbol (boolean, tristate, string, ...)\\n\"\n\t\"o The line 'Prompt:' shows the text used in the menu structure for\\n\"\n\t\"  this symbol\\n\"\n\t\"o The 'Defined at' line tells at what file / line number the symbol\\n\"\n\t\"  is defined\\n\"\n\t\"o The 'Depends on:' line tells what symbols need to be defined for\\n\"\n\t\"  this symbol to be visible in the menu (selectable)\\n\"\n\t\"o The 'Location:' lines tells where in the menu structure this symbol\\n\"\n\t\"  is located\\n\"\n\t\"    A location followed by a [=y] indicates that this is a\\n\"\n\t\"    selectable menu item - and the current value is displayed inside\\n\"\n\t\"    brackets.\\n\"\n\t\"    Press the key in the (#) prefix to jump directly to that\\n\"\n\t\"    location. You will be returned to the current search results\\n\"\n\t\"    after exiting this new menu.\\n\"\n\t\"o The 'Selects:' line tells what symbols will be automatically\\n\"\n\t\"  selected if this symbol is selected (y or m)\\n\"\n\t\"o The 'Selected by' line tells what symbol has selected this symbol\\n\"\n\t\"\\n\"\n\t\"Only relevant lines are shown.\\n\"\n\t\"\\n\\n\"\n\t\"Search examples:\\n\"\n\t\"Examples: USB\t=> find all symbols containing USB\\n\"\n\t\"          ^USB => find all symbols starting with USB\\n\"\n\t\"          USB$ => find all symbols ending with USB\\n\"\n\t\"\\n\");\n\nstatic int indent;\nstatic struct menu *current_menu;\nstatic int child_count;\nstatic int single_menu_mode;\nstatic int show_all_options;\nstatic int save_and_exit;\n\nstatic void conf(struct menu *menu, struct menu *active_menu);\nstatic void conf_choice(struct menu *menu);\nstatic void conf_string(struct menu *menu);\nstatic void conf_load(void);\nstatic void conf_save(void);\nstatic int show_textbox_ext(const char *title, char *text, int r, int c,\n\t\t\t    int *keys, int *vscroll, int *hscroll,\n\t\t\t    update_text_fn update_text, void *data);\nstatic void show_textbox(const char *title, const char *text, int r, int c);\nstatic void show_helptext(const char *title, const char *text);\nstatic void show_help(struct menu *menu);\n\nstatic char filename[PATH_MAX+1];\nstatic void set_config_filename(const char *config_filename)\n{\n\tstatic char menu_backtitle[PATH_MAX+128];\n\tint size;\n\n\tsize = snprintf(menu_backtitle, sizeof(menu_backtitle),\n\t                \"%s - %s\", config_filename, rootmenu.prompt->text);\n\tif (size >= sizeof(menu_backtitle))\n\t\tmenu_backtitle[sizeof(menu_backtitle)-1] = '\\0';\n\tset_dialog_backtitle(menu_backtitle);\n\n\tsize = snprintf(filename, sizeof(filename), \"%s\", config_filename);\n\tif (size >= sizeof(filename))\n\t\tfilename[sizeof(filename)-1] = '\\0';\n}\n\nstruct subtitle_part {\n\tstruct list_head entries;\n\tconst char *text;\n};\nstatic LIST_HEAD(trail);\n\nstatic struct subtitle_list *subtitles;\nstatic void set_subtitle(void)\n{\n\tstruct subtitle_part *sp;\n\tstruct subtitle_list *pos, *tmp;\n\n\tfor (pos = subtitles; pos != NULL; pos = tmp) {\n\t\ttmp = pos->next;\n\t\tfree(pos);\n\t}\n\n\tsubtitles = NULL;\n\tlist_for_each_entry(sp, &trail, entries) {\n\t\tif (sp->text) {\n\t\t\tif (pos) {\n\t\t\t\tpos->next = xcalloc(sizeof(*pos), 1);\n\t\t\t\tpos = pos->next;\n\t\t\t} else {\n\t\t\t\tsubtitles = pos = xcalloc(sizeof(*pos), 1);\n\t\t\t}\n\t\t\tpos->text = sp->text;\n\t\t}\n\t}\n\n\tset_dialog_subtitles(subtitles);\n}\n\nstatic void reset_subtitle(void)\n{\n\tstruct subtitle_list *pos, *tmp;\n\n\tfor (pos = subtitles; pos != NULL; pos = tmp) {\n\t\ttmp = pos->next;\n\t\tfree(pos);\n\t}\n\tsubtitles = NULL;\n\tset_dialog_subtitles(subtitles);\n}\n\nstruct search_data {\n\tstruct list_head *head;\n\tstruct menu **targets;\n\tint *keys;\n};\n\nstatic void update_text(char *buf, size_t start, size_t end, void *_data)\n{\n\tstruct search_data *data = _data;\n\tstruct jump_key *pos;\n\tint k = 0;\n\n\tlist_for_each_entry(pos, data->head, entries) {\n\t\tif (pos->offset >= start && pos->offset < end) {\n\t\t\tchar header[4];\n\n\t\t\tif (k < JUMP_NB) {\n\t\t\t\tint key = '0' + (pos->index % JUMP_NB) + 1;\n\n\t\t\t\tsprintf(header, \"(%c)\", key);\n\t\t\t\tdata->keys[k] = key;\n\t\t\t\tdata->targets[k] = pos->target;\n\t\t\t\tk++;\n\t\t\t} else {\n\t\t\t\tsprintf(header, \"   \");\n\t\t\t}\n\n\t\t\tmemcpy(buf + pos->offset, header, sizeof(header) - 1);\n\t\t}\n\t}\n\tdata->keys[k] = 0;\n}\n\nstatic void search_conf(void)\n{\n\tstruct symbol **sym_arr;\n\tstruct gstr res;\n\tstruct gstr title;\n\tchar *dialog_input;\n\tint dres, vscroll = 0, hscroll = 0;\n\tbool again;\n\tstruct gstr sttext;\n\tstruct subtitle_part stpart;\n\n\ttitle = str_new();\n\tstr_printf( &title, _(\"Enter (sub)string or regexp to search for \"\n\t\t\t      \"(with or without \\\"%s\\\")\"), CONFIG_);\n\nagain:\n\tdialog_clear();\n\tdres = dialog_inputbox(_(\"Search Configuration Parameter\"),\n\t\t\t      str_get(&title),\n\t\t\t      10, 75, \"\");\n\tswitch (dres) {\n\tcase 0:\n\t\tbreak;\n\tcase 1:\n\t\tshow_helptext(_(\"Search Configuration\"), search_help);\n\t\tgoto again;\n\tdefault:\n\t\tstr_free(&title);\n\t\treturn;\n\t}\n\n\t/* strip the prefix if necessary */\n\tdialog_input = dialog_input_result;\n\tif (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)\n\t\tdialog_input += strlen(CONFIG_);\n\n\tsttext = str_new();\n\tstr_printf(&sttext, \"Search (%s)\", dialog_input_result);\n\tstpart.text = str_get(&sttext);\n\tlist_add_tail(&stpart.entries, &trail);\n\n\tsym_arr = sym_re_search(dialog_input);\n\tdo {\n\t\tLIST_HEAD(head);\n\t\tstruct menu *targets[JUMP_NB];\n\t\tint keys[JUMP_NB + 1], i;\n\t\tstruct search_data data = {\n\t\t\t.head = &head,\n\t\t\t.targets = targets,\n\t\t\t.keys = keys,\n\t\t};\n\t\tstruct jump_key *pos, *tmp;\n\n\t\tres = get_relations_str(sym_arr, &head);\n\t\tset_subtitle();\n\t\tdres = show_textbox_ext(_(\"Search Results\"), (char *)\n\t\t\t\t\tstr_get(&res), 0, 0, keys, &vscroll,\n\t\t\t\t\t&hscroll, &update_text, (void *)\n\t\t\t\t\t&data);\n\t\tagain = false;\n\t\tfor (i = 0; i < JUMP_NB && keys[i]; i++)\n\t\t\tif (dres == keys[i]) {\n\t\t\t\tconf(targets[i]->parent, targets[i]);\n\t\t\t\tagain = true;\n\t\t\t}\n\t\tstr_free(&res);\n\t\tlist_for_each_entry_safe(pos, tmp, &head, entries)\n\t\t\tfree(pos);\n\t} while (again);\n\tfree(sym_arr);\n\tstr_free(&title);\n\tlist_del(trail.prev);\n\tstr_free(&sttext);\n}\n\nstatic void build_conf(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct menu *child;\n\tint type, tmp, doint = 2;\n\ttristate val;\n\tchar ch;\n\tbool visible;\n\n\t/*\n\t * note: menu_is_visible() has side effect that it will\n\t * recalc the value of the symbol.\n\t */\n\tvisible = menu_is_visible(menu);\n\tif (show_all_options && !menu_has_prompt(menu))\n\t\treturn;\n\telse if (!show_all_options && !visible)\n\t\treturn;\n\n\tsym = menu->sym;\n\tprop = menu->prompt;\n\tif (!sym) {\n\t\tif (prop && menu != current_menu) {\n\t\t\tconst char *prompt = menu_get_prompt(menu);\n\t\t\tswitch (prop->type) {\n\t\t\tcase P_MENU:\n\t\t\t\tchild_count++;\n\t\t\t\tprompt = _(prompt);\n\t\t\t\tif (single_menu_mode) {\n\t\t\t\t\titem_make(\"%s%*c%s\",\n\t\t\t\t\t\t  menu->data ? \"-->\" : \"++>\",\n\t\t\t\t\t\t  indent + 1, ' ', prompt);\n\t\t\t\t} else\n\t\t\t\t\titem_make(\"   %*c%s  %s\",\n\t\t\t\t\t\t  indent + 1, ' ', prompt,\n\t\t\t\t\t\t  menu_is_empty(menu) ? \"----\" : \"--->\");\n\t\t\t\titem_set_tag('m');\n\t\t\t\titem_set_data(menu);\n\t\t\t\tif (single_menu_mode && menu->data)\n\t\t\t\t\tgoto conf_childs;\n\t\t\t\treturn;\n\t\t\tcase P_COMMENT:\n\t\t\t\tif (prompt) {\n\t\t\t\t\tchild_count++;\n\t\t\t\t\titem_make(\"   %*c*** %s ***\", indent + 1, ' ', _(prompt));\n\t\t\t\t\titem_set_tag(':');\n\t\t\t\t\titem_set_data(menu);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (prompt) {\n\t\t\t\t\tchild_count++;\n\t\t\t\t\titem_make(\"---%*c%s\", indent + 1, ' ', _(prompt));\n\t\t\t\t\titem_set_tag(':');\n\t\t\t\t\titem_set_data(menu);\n\t\t\t\t}\n\t\t\t}\n\t\t} else\n\t\t\tdoint = 0;\n\t\tgoto conf_childs;\n\t}\n\n\ttype = sym_get_type(sym);\n\tif (sym_is_choice(sym)) {\n\t\tstruct symbol *def_sym = sym_get_choice_value(sym);\n\t\tstruct menu *def_menu = NULL;\n\n\t\tchild_count++;\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (menu_is_visible(child) && child->sym == def_sym)\n\t\t\t\tdef_menu = child;\n\t\t}\n\n\t\tval = sym_get_tristate_value(sym);\n\t\tif (sym_is_changable(sym)) {\n\t\t\tswitch (type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\t\titem_make(\"[%c]\", val == no ? ' ' : '*');\n\t\t\t\tbreak;\n\t\t\tcase S_TRISTATE:\n\t\t\t\tswitch (val) {\n\t\t\t\tcase yes: ch = '*'; break;\n\t\t\t\tcase mod: ch = 'M'; break;\n\t\t\t\tdefault:  ch = ' '; break;\n\t\t\t\t}\n\t\t\t\titem_make(\"<%c>\", ch);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\titem_set_tag('t');\n\t\t\titem_set_data(menu);\n\t\t} else {\n\t\t\titem_make(\"   \");\n\t\t\titem_set_tag(def_menu ? 't' : ':');\n\t\t\titem_set_data(menu);\n\t\t}\n\n\t\titem_add_str(\"%*c%s\", indent + 1, ' ', _(menu_get_prompt(menu)));\n\t\tif (val == yes) {\n\t\t\tif (def_menu) {\n\t\t\t\titem_add_str(\" (%s)\", _(menu_get_prompt(def_menu)));\n\t\t\t\titem_add_str(\"  --->\");\n\t\t\t\tif (def_menu->list) {\n\t\t\t\t\tindent += 2;\n\t\t\t\t\tbuild_conf(def_menu);\n\t\t\t\t\tindent -= 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tif (menu == current_menu) {\n\t\t\titem_make(\"---%*c%s\", indent + 1, ' ', _(menu_get_prompt(menu)));\n\t\t\titem_set_tag(':');\n\t\t\titem_set_data(menu);\n\t\t\tgoto conf_childs;\n\t\t}\n\t\tchild_count++;\n\t\tval = sym_get_tristate_value(sym);\n\t\tif (sym_is_choice_value(sym) && val == yes) {\n\t\t\titem_make(\"   \");\n\t\t\titem_set_tag(':');\n\t\t\titem_set_data(menu);\n\t\t} else {\n\t\t\tswitch (type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\t\tif (sym_is_changable(sym))\n\t\t\t\t\titem_make(\"[%c]\", val == no ? ' ' : '*');\n\t\t\t\telse\n\t\t\t\t\titem_make(\"-%c-\", val == no ? ' ' : '*');\n\t\t\t\titem_set_tag('t');\n\t\t\t\titem_set_data(menu);\n\t\t\t\tbreak;\n\t\t\tcase S_TRISTATE:\n\t\t\t\tswitch (val) {\n\t\t\t\tcase yes: ch = '*'; break;\n\t\t\t\tcase mod: ch = 'M'; break;\n\t\t\t\tdefault:  ch = ' '; break;\n\t\t\t\t}\n\t\t\t\tif (sym_is_changable(sym)) {\n\t\t\t\t\tif (sym->rev_dep.tri == mod)\n\t\t\t\t\t\titem_make(\"{%c}\", ch);\n\t\t\t\t\telse\n\t\t\t\t\t\titem_make(\"<%c>\", ch);\n\t\t\t\t} else\n\t\t\t\t\titem_make(\"-%c-\", ch);\n\t\t\t\titem_set_tag('t');\n\t\t\t\titem_set_data(menu);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\ttmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */\n\t\t\t\titem_make(\"(%s)\", sym_get_string_value(sym));\n\t\t\t\ttmp = indent - tmp + 4;\n\t\t\t\tif (tmp < 0)\n\t\t\t\t\ttmp = 0;\n\t\t\t\titem_add_str(\"%*c%s%s\", tmp, ' ', _(menu_get_prompt(menu)),\n\t\t\t\t\t     (sym_has_value(sym) || !sym_is_changable(sym)) ?\n\t\t\t\t\t     \"\" : _(\" (NEW)\"));\n\t\t\t\titem_set_tag('s');\n\t\t\t\titem_set_data(menu);\n\t\t\t\tgoto conf_childs;\n\t\t\t}\n\t\t}\n\t\titem_add_str(\"%*c%s%s\", indent + 1, ' ', _(menu_get_prompt(menu)),\n\t\t\t  (sym_has_value(sym) || !sym_is_changable(sym)) ?\n\t\t\t  \"\" : _(\" (NEW)\"));\n\t\tif (menu->prompt->type == P_MENU) {\n\t\t\titem_add_str(\"  %s\", menu_is_empty(menu) ? \"----\" : \"--->\");\n\t\t\treturn;\n\t\t}\n\t}\n\nconf_childs:\n\tindent += doint;\n\tfor (child = menu->list; child; child = child->next)\n\t\tbuild_conf(child);\n\tindent -= doint;\n}\n\nstatic void conf(struct menu *menu, struct menu *active_menu)\n{\n\tstruct menu *submenu;\n\tconst char *prompt = menu_get_prompt(menu);\n\tstruct subtitle_part stpart;\n\tstruct symbol *sym;\n\tint res;\n\tint s_scroll = 0;\n\n\tif (menu != &rootmenu)\n\t\tstpart.text = menu_get_prompt(menu);\n\telse\n\t\tstpart.text = NULL;\n\tlist_add_tail(&stpart.entries, &trail);\n\n\twhile (1) {\n\t\titem_reset();\n\t\tcurrent_menu = menu;\n\t\tbuild_conf(menu);\n\t\tif (!child_count)\n\t\t\tbreak;\n\t\tset_subtitle();\n\t\tdialog_clear();\n\t\tres = dialog_menu(prompt ? _(prompt) : _(\"Main Menu\"),\n\t\t\t\t  _(menu_instructions),\n\t\t\t\t  active_menu, &s_scroll);\n\t\tif (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)\n\t\t\tbreak;\n\t\tif (item_count() != 0) {\n\t\t\tif (!item_activate_selected())\n\t\t\t\tcontinue;\n\t\t\tif (!item_tag())\n\t\t\t\tcontinue;\n\t\t}\n\t\tsubmenu = item_data();\n\t\tactive_menu = item_data();\n\t\tif (submenu)\n\t\t\tsym = submenu->sym;\n\t\telse\n\t\t\tsym = NULL;\n\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tswitch (item_tag()) {\n\t\t\tcase 'm':\n\t\t\t\tif (single_menu_mode)\n\t\t\t\t\tsubmenu->data = (void *) (long) !submenu->data;\n\t\t\t\telse\n\t\t\t\t\tconf(submenu, NULL);\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\tif (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)\n\t\t\t\t\tconf_choice(submenu);\n\t\t\t\telse if (submenu->prompt->type == P_MENU)\n\t\t\t\t\tconf(submenu, NULL);\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tconf_string(submenu);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tif (sym)\n\t\t\t\tshow_help(submenu);\n\t\t\telse {\n\t\t\t\treset_subtitle();\n\t\t\t\tshow_helptext(_(\"README\"), _(mconf_readme));\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\treset_subtitle();\n\t\t\tconf_save();\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\treset_subtitle();\n\t\t\tconf_load();\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tif (item_is_tag('t')) {\n\t\t\t\tif (sym_set_tristate_value(sym, yes))\n\t\t\t\t\tbreak;\n\t\t\t\tif (sym_set_tristate_value(sym, mod))\n\t\t\t\t\tshow_textbox(NULL, setmod_text, 6, 74);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_set_tristate_value(sym, no);\n\t\t\tbreak;\n\t\tcase 7:\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_set_tristate_value(sym, mod);\n\t\t\tbreak;\n\t\tcase 8:\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_toggle_tristate_value(sym);\n\t\t\telse if (item_is_tag('m'))\n\t\t\t\tconf(submenu, NULL);\n\t\t\tbreak;\n\t\tcase 9:\n\t\t\tsearch_conf();\n\t\t\tbreak;\n\t\tcase 10:\n\t\t\tshow_all_options = !show_all_options;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlist_del(trail.prev);\n}\n\nstatic int show_textbox_ext(const char *title, char *text, int r, int c, int\n\t\t\t    *keys, int *vscroll, int *hscroll, update_text_fn\n\t\t\t    update_text, void *data)\n{\n\tdialog_clear();\n\treturn dialog_textbox(title, text, r, c, keys, vscroll, hscroll,\n\t\t\t      update_text, data);\n}\n\nstatic void show_textbox(const char *title, const char *text, int r, int c)\n{\n\tshow_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,\n\t\t\t NULL, NULL);\n}\n\nstatic void show_helptext(const char *title, const char *text)\n{\n\tshow_textbox(title, text, 0, 0);\n}\n\nstatic void conf_message_callback(const char *fmt, va_list ap)\n{\n\tchar buf[PATH_MAX+1];\n\n\tvsnprintf(buf, sizeof(buf), fmt, ap);\n\tif (save_and_exit)\n\t\tprintf(\"%s\", buf);\n\telse\n\t\tshow_textbox(NULL, buf, 6, 60);\n}\n\nstatic void show_help(struct menu *menu)\n{\n\tstruct gstr help = str_new();\n\n\thelp.max_width = getmaxx(stdscr) - 10;\n\tmenu_get_ext_help(menu, &help);\n\n\tshow_helptext(_(menu_get_prompt(menu)), str_get(&help));\n\tstr_free(&help);\n}\n\nstatic void conf_choice(struct menu *menu)\n{\n\tconst char *prompt = _(menu_get_prompt(menu));\n\tstruct menu *child;\n\tstruct symbol *active;\n\n\tactive = sym_get_choice_value(menu->sym);\n\twhile (1) {\n\t\tint res;\n\t\tint selected;\n\t\titem_reset();\n\n\t\tcurrent_menu = menu;\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (!menu_is_visible(child))\n\t\t\t\tcontinue;\n\t\t\tif (child->sym)\n\t\t\t\titem_make(\"%s\", _(menu_get_prompt(child)));\n\t\t\telse {\n\t\t\t\titem_make(\"*** %s ***\", _(menu_get_prompt(child)));\n\t\t\t\titem_set_tag(':');\n\t\t\t}\n\t\t\titem_set_data(child);\n\t\t\tif (child->sym == active)\n\t\t\t\titem_set_selected(1);\n\t\t\tif (child->sym == sym_get_choice_value(menu->sym))\n\t\t\t\titem_set_tag('X');\n\t\t}\n\t\tdialog_clear();\n\t\tres = dialog_checklist(prompt ? _(prompt) : _(\"Main Menu\"),\n\t\t\t\t\t_(radiolist_instructions),\n\t\t\t\t\tMENUBOX_HEIGTH_MIN,\n\t\t\t\t\tMENUBOX_WIDTH_MIN,\n\t\t\t\t\tCHECKLIST_HEIGTH_MIN);\n\t\tselected = item_activate_selected();\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (selected) {\n\t\t\t\tchild = item_data();\n\t\t\t\tif (!child->sym)\n\t\t\t\t\tbreak;\n\n\t\t\t\tsym_set_tristate_value(child->sym, yes);\n\t\t\t}\n\t\t\treturn;\n\t\tcase 1:\n\t\t\tif (selected) {\n\t\t\t\tchild = item_data();\n\t\t\t\tshow_help(child);\n\t\t\t\tactive = child->sym;\n\t\t\t} else\n\t\t\t\tshow_help(menu);\n\t\t\tbreak;\n\t\tcase KEY_ESC:\n\t\t\treturn;\n\t\tcase -ERRDISPLAYTOOSMALL:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_string(struct menu *menu)\n{\n\tconst char *prompt = menu_get_prompt(menu);\n\n\twhile (1) {\n\t\tint res;\n\t\tconst char *heading;\n\n\t\tswitch (sym_get_type(menu->sym)) {\n\t\tcase S_INT:\n\t\t\theading = _(inputbox_instructions_int);\n\t\t\tbreak;\n\t\tcase S_HEX:\n\t\t\theading = _(inputbox_instructions_hex);\n\t\t\tbreak;\n\t\tcase S_STRING:\n\t\t\theading = _(inputbox_instructions_string);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\theading = _(\"Internal mconf error!\");\n\t\t}\n\t\tdialog_clear();\n\t\tres = dialog_inputbox(prompt ? _(prompt) : _(\"Main Menu\"),\n\t\t\t\t      heading, 10, 75,\n\t\t\t\t      sym_get_string_value(menu->sym));\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (sym_set_string_value(menu->sym, dialog_input_result))\n\t\t\t\treturn;\n\t\t\tshow_textbox(NULL, _(\"You have made an invalid entry.\"), 5, 43);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_help(menu);\n\t\t\tbreak;\n\t\tcase KEY_ESC:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_load(void)\n{\n\n\twhile (1) {\n\t\tint res;\n\t\tdialog_clear();\n\t\tres = dialog_inputbox(NULL, load_config_text,\n\t\t\t\t      11, 55, filename);\n\t\tswitch(res) {\n\t\tcase 0:\n\t\t\tif (!dialog_input_result[0])\n\t\t\t\treturn;\n\t\t\tif (!conf_read(dialog_input_result)) {\n\t\t\t\tset_config_filename(dialog_input_result);\n\t\t\t\tsym_set_change_count(1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tshow_textbox(NULL, _(\"File does not exist!\"), 5, 38);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_helptext(_(\"Load Alternate Configuration\"), load_config_help);\n\t\t\tbreak;\n\t\tcase KEY_ESC:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_save(void)\n{\n\twhile (1) {\n\t\tint res;\n\t\tdialog_clear();\n\t\tres = dialog_inputbox(NULL, save_config_text,\n\t\t\t\t      11, 55, filename);\n\t\tswitch(res) {\n\t\tcase 0:\n\t\t\tif (!dialog_input_result[0])\n\t\t\t\treturn;\n\t\t\tif (!conf_write(dialog_input_result)) {\n\t\t\t\tset_config_filename(dialog_input_result);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tshow_textbox(NULL, _(\"Can't create file!  Probably a nonexistent directory.\"), 5, 60);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_helptext(_(\"Save Alternate Configuration\"), save_config_help);\n\t\t\tbreak;\n\t\tcase KEY_ESC:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic int handle_exit(void)\n{\n\tint res;\n\n\tsave_and_exit = 1;\n\treset_subtitle();\n\tdialog_clear();\n\tif (conf_get_changed())\n\t\tres = dialog_yesno(NULL,\n\t\t\t\t   _(\"Do you wish to save your new configuration?\\n\"\n\t\t\t\t     \"(Press <ESC><ESC> to continue configuration.)\"),\n\t\t\t\t   6, 60);\n\telse\n\t\tres = -1;\n\n\tend_dialog(saved_x, saved_y);\n\n\tswitch (res) {\n\tcase 0:\n\t\tif (conf_write(filename)) {\n\t\t\tfprintf(stderr, _(\"\\n\\n\"\n\t\t\t\t\t  \"Error while writing of the configuration.\\n\"\n\t\t\t\t\t  \"Your configuration changes were NOT saved.\"\n\t\t\t\t\t  \"\\n\\n\"));\n\t\t\treturn 1;\n\t\t}\n\t\t/* fall through */\n\tcase -1:\n\t\tprintf(_(\"\\n\\n\"\n\t\t\t \"*** End of the configuration.\\n\"\n\t\t\t \"*** Execute 'make' to start the build or try 'make help'.\"\n\t\t\t \"\\n\\n\"));\n\t\tres = 0;\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, _(\"\\n\\n\"\n\t\t\t\t  \"Your configuration changes were NOT saved.\"\n\t\t\t\t  \"\\n\\n\"));\n\t\tif (res != KEY_ESC)\n\t\t\tres = 0;\n\t}\n\n\treturn res;\n}\n\nstatic void sig_handler(int signo)\n{\n\texit(handle_exit());\n}\n\nint main(int ac, char **av)\n{\n\tchar *mode;\n\tint res;\n\n\tsetlocale(LC_ALL, \"\");\n\tbindtextdomain(PACKAGE, LOCALEDIR);\n\ttextdomain(PACKAGE);\n\n\tsignal(SIGINT, sig_handler);\n\n\tconf_parse(av[1]);\n\tconf_read(NULL);\n\n\tmode = getenv(\"MENUCONFIG_MODE\");\n\tif (mode) {\n\t\tif (!strcasecmp(mode, \"single_menu\"))\n\t\t\tsingle_menu_mode = 1;\n\t}\n\n\tif (init_dialog(NULL)) {\n\t\tfprintf(stderr, N_(\"Your display is too small to run Menuconfig!\\n\"));\n\t\tfprintf(stderr, N_(\"It must be at least 19 lines by 80 columns.\\n\"));\n\t\treturn 1;\n\t}\n\n\tset_config_filename(conf_get_configname());\n\tconf_set_message_callback(conf_message_callback);\n\tdo {\n\t\tconf(&rootmenu, NULL);\n\t\tres = handle_exit();\n\t} while (res == KEY_ESC);\n\n\treturn res;\n}\n\n"
  },
  {
    "path": "kconfig/menu.c",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"lkc.h\"\n\nstatic const char nohelp_text[] = \"There is no help available for this option.\";\n\nstruct menu rootmenu;\nstatic struct menu **last_entry_ptr;\n\nstruct file *file_list;\nstruct file *current_file;\n\nvoid menu_warn(struct menu *menu, const char *fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s:%d:warning: \", menu->file->name, menu->lineno);\n\tvfprintf(stderr, fmt, ap);\n\tfprintf(stderr, \"\\n\");\n\tva_end(ap);\n}\n\nstatic void prop_warn(struct property *prop, const char *fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s:%d:warning: \", prop->file->name, prop->lineno);\n\tvfprintf(stderr, fmt, ap);\n\tfprintf(stderr, \"\\n\");\n\tva_end(ap);\n}\n\nvoid _menu_init(void)\n{\n\tcurrent_entry = current_menu = &rootmenu;\n\tlast_entry_ptr = &rootmenu.list;\n}\n\nvoid menu_add_entry(struct symbol *sym)\n{\n\tstruct menu *menu;\n\n\tmenu = xmalloc(sizeof(*menu));\n\tmemset(menu, 0, sizeof(*menu));\n\tmenu->sym = sym;\n\tmenu->parent = current_menu;\n\tmenu->file = current_file;\n\tmenu->lineno = zconf_lineno();\n\n\t*last_entry_ptr = menu;\n\tlast_entry_ptr = &menu->next;\n\tcurrent_entry = menu;\n\tif (sym)\n\t\tmenu_add_symbol(P_SYMBOL, sym, NULL);\n}\n\nvoid menu_end_entry(void)\n{\n}\n\nstruct menu *menu_add_menu(void)\n{\n\tmenu_end_entry();\n\tlast_entry_ptr = &current_entry->list;\n\treturn current_menu = current_entry;\n}\n\nvoid menu_end_menu(void)\n{\n\tlast_entry_ptr = &current_menu->next;\n\tcurrent_menu = current_menu->parent;\n}\n\nstatic struct expr *menu_check_dep(struct expr *e)\n{\n\tif (!e)\n\t\treturn e;\n\n\tswitch (e->type) {\n\tcase E_NOT:\n\t\te->left.expr = menu_check_dep(e->left.expr);\n\t\tbreak;\n\tcase E_OR:\n\tcase E_AND:\n\t\te->left.expr = menu_check_dep(e->left.expr);\n\t\te->right.expr = menu_check_dep(e->right.expr);\n\t\tbreak;\n\tcase E_SYMBOL:\n\t\t/* change 'm' into 'm' && MODULES */\n\t\tif (e->left.sym == &symbol_mod)\n\t\t\treturn expr_alloc_and(e, expr_alloc_symbol(modules_sym));\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn e;\n}\n\nvoid menu_add_dep(struct expr *dep)\n{\n\tcurrent_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));\n}\n\nvoid menu_set_type(int type)\n{\n\tstruct symbol *sym = current_entry->sym;\n\n\tif (sym->type == type)\n\t\treturn;\n\tif (sym->type == S_UNKNOWN) {\n\t\tsym->type = type;\n\t\treturn;\n\t}\n\tmenu_warn(current_entry,\n\t\t\"ignoring type redefinition of '%s' from '%s' to '%s'\",\n\t\tsym->name ? sym->name : \"<choice>\",\n\t\tsym_type_name(sym->type), sym_type_name(type));\n}\n\nstruct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)\n{\n\tstruct property *prop = prop_alloc(type, current_entry->sym);\n\n\tprop->menu = current_entry;\n\tprop->expr = expr;\n\tprop->visible.expr = menu_check_dep(dep);\n\n\tif (prompt) {\n\t\tif (isspace(*prompt)) {\n\t\t\tprop_warn(prop, \"leading whitespace ignored\");\n\t\t\twhile (isspace(*prompt))\n\t\t\t\tprompt++;\n\t\t}\n\t\tif (current_entry->prompt && current_entry != &rootmenu)\n\t\t\tprop_warn(prop, \"prompt redefined\");\n\n\t\t/* Apply all upper menus' visibilities to actual prompts. */\n\t\tif(type == P_PROMPT) {\n\t\t\tstruct menu *menu = current_entry;\n\n\t\t\twhile ((menu = menu->parent) != NULL) {\n\t\t\t\tstruct expr *dup_expr;\n\n\t\t\t\tif (!menu->visibility)\n\t\t\t\t\tcontinue;\n\t\t\t\t/*\n\t\t\t\t * Do not add a reference to the\n\t\t\t\t * menu's visibility expression but\n\t\t\t\t * use a copy of it.  Otherwise the\n\t\t\t\t * expression reduction functions\n\t\t\t\t * will modify expressions that have\n\t\t\t\t * multiple references which can\n\t\t\t\t * cause unwanted side effects.\n\t\t\t\t */\n\t\t\t\tdup_expr = expr_copy(menu->visibility);\n\n\t\t\t\tprop->visible.expr\n\t\t\t\t\t= expr_alloc_and(prop->visible.expr,\n\t\t\t\t\t\t\t dup_expr);\n\t\t\t}\n\t\t}\n\n\t\tcurrent_entry->prompt = prop;\n\t}\n\tprop->text = prompt;\n\n\treturn prop;\n}\n\nstruct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)\n{\n\treturn menu_add_prop(type, prompt, NULL, dep);\n}\n\nvoid menu_add_visibility(struct expr *expr)\n{\n\tcurrent_entry->visibility = expr_alloc_and(current_entry->visibility,\n\t    expr);\n}\n\nvoid menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)\n{\n\tmenu_add_prop(type, NULL, expr, dep);\n}\n\nvoid menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)\n{\n\tmenu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);\n}\n\nvoid menu_add_option(int token, char *arg)\n{\n\tswitch (token) {\n\tcase T_OPT_MODULES:\n\t\tif (modules_sym)\n\t\t\tzconf_error(\"symbol '%s' redefines option 'modules'\"\n\t\t\t\t    \" already defined by symbol '%s'\",\n\t\t\t\t    current_entry->sym->name,\n\t\t\t\t    modules_sym->name\n\t\t\t\t    );\n\t\tmodules_sym = current_entry->sym;\n\t\tbreak;\n\tcase T_OPT_DEFCONFIG_LIST:\n\t\tif (!sym_defconfig_list)\n\t\t\tsym_defconfig_list = current_entry->sym;\n\t\telse if (sym_defconfig_list != current_entry->sym)\n\t\t\tzconf_error(\"trying to redefine defconfig symbol\");\n\t\tbreak;\n\tcase T_OPT_ENV:\n\t\tprop_add_env(arg);\n\t\tbreak;\n\tcase T_OPT_ALLNOCONFIG_Y:\n\t\tcurrent_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;\n\t\tbreak;\n\t}\n}\n\nstatic int menu_validate_number(struct symbol *sym, struct symbol *sym2)\n{\n\treturn sym2->type == S_INT || sym2->type == S_HEX ||\n\t       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));\n}\n\nstatic void sym_check_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\tstruct symbol *sym2;\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tswitch (prop->type) {\n\t\tcase P_DEFAULT:\n\t\t\tif ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&\n\t\t\t    prop->expr->type != E_SYMBOL)\n\t\t\t\tprop_warn(prop,\n\t\t\t\t    \"default for config symbol '%s'\"\n\t\t\t\t    \" must be a single symbol\", sym->name);\n\t\t\tif (prop->expr->type != E_SYMBOL)\n\t\t\t\tbreak;\n\t\t\tsym2 = prop_get_symbol(prop);\n\t\t\tif (sym->type == S_HEX || sym->type == S_INT) {\n\t\t\t\tif (!menu_validate_number(sym, sym2))\n\t\t\t\t\tprop_warn(prop,\n\t\t\t\t\t    \"'%s': number is invalid\",\n\t\t\t\t\t    sym->name);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase P_SELECT:\n\t\t\tsym2 = prop_get_symbol(prop);\n\t\t\tif (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)\n\t\t\t\tprop_warn(prop,\n\t\t\t\t    \"config symbol '%s' uses select, but is \"\n\t\t\t\t    \"not boolean or tristate\", sym->name);\n\t\t\telse if (sym2->type != S_UNKNOWN &&\n\t\t\t         sym2->type != S_BOOLEAN &&\n\t\t\t         sym2->type != S_TRISTATE)\n\t\t\t\tprop_warn(prop,\n\t\t\t\t    \"'%s' has wrong type. 'select' only \"\n\t\t\t\t    \"accept arguments of boolean and \"\n\t\t\t\t    \"tristate type\", sym2->name);\n\t\t\tbreak;\n\t\tcase P_RANGE:\n\t\t\tif (sym->type != S_INT && sym->type != S_HEX)\n\t\t\t\tprop_warn(prop, \"range is only allowed \"\n\t\t\t\t                \"for int or hex symbols\");\n\t\t\tif (!menu_validate_number(sym, prop->expr->left.sym) ||\n\t\t\t    !menu_validate_number(sym, prop->expr->right.sym))\n\t\t\t\tprop_warn(prop, \"range is invalid\");\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t}\n}\n\nvoid menu_finalize(struct menu *parent)\n{\n\tstruct menu *menu, *last_menu;\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct expr *parentdep, *basedep, *dep, *dep2, **ep;\n\n\tsym = parent->sym;\n\tif (parent->list) {\n\t\tif (sym && sym_is_choice(sym)) {\n\t\t\tif (sym->type == S_UNKNOWN) {\n\t\t\t\t/* find the first choice value to find out choice type */\n\t\t\t\tcurrent_entry = parent;\n\t\t\t\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\t\t\t\tif (menu->sym && menu->sym->type != S_UNKNOWN) {\n\t\t\t\t\t\tmenu_set_type(menu->sym->type);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* set the type of the remaining choice values */\n\t\t\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\t\t\tcurrent_entry = menu;\n\t\t\t\tif (menu->sym && menu->sym->type == S_UNKNOWN)\n\t\t\t\t\tmenu_set_type(sym->type);\n\t\t\t}\n\t\t\tparentdep = expr_alloc_symbol(sym);\n\t\t} else if (parent->prompt)\n\t\t\tparentdep = parent->prompt->visible.expr;\n\t\telse\n\t\t\tparentdep = parent->dep;\n\n\t\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\t\tbasedep = expr_transform(menu->dep);\n\t\t\tbasedep = expr_alloc_and(expr_copy(parentdep), basedep);\n\t\t\tbasedep = expr_eliminate_dups(basedep);\n\t\t\tmenu->dep = basedep;\n\t\t\tif (menu->sym)\n\t\t\t\tprop = menu->sym->prop;\n\t\t\telse\n\t\t\t\tprop = menu->prompt;\n\t\t\tfor (; prop; prop = prop->next) {\n\t\t\t\tif (prop->menu != menu)\n\t\t\t\t\tcontinue;\n\t\t\t\tdep = expr_transform(prop->visible.expr);\n\t\t\t\tdep = expr_alloc_and(expr_copy(basedep), dep);\n\t\t\t\tdep = expr_eliminate_dups(dep);\n\t\t\t\tif (menu->sym && menu->sym->type != S_TRISTATE)\n\t\t\t\t\tdep = expr_trans_bool(dep);\n\t\t\t\tprop->visible.expr = dep;\n\t\t\t\tif (prop->type == P_SELECT) {\n\t\t\t\t\tstruct symbol *es = prop_get_symbol(prop);\n\t\t\t\t\tes->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,\n\t\t\t\t\t\t\texpr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (menu = parent->list; menu; menu = menu->next)\n\t\t\tmenu_finalize(menu);\n\t} else if (sym) {\n\t\tbasedep = parent->prompt ? parent->prompt->visible.expr : NULL;\n\t\tbasedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);\n\t\tbasedep = expr_eliminate_dups(expr_transform(basedep));\n\t\tlast_menu = NULL;\n\t\tfor (menu = parent->next; menu; menu = menu->next) {\n\t\t\tdep = menu->prompt ? menu->prompt->visible.expr : menu->dep;\n\t\t\tif (!expr_contains_symbol(dep, sym))\n\t\t\t\tbreak;\n\t\t\tif (expr_depends_symbol(dep, sym))\n\t\t\t\tgoto next;\n\t\t\tdep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);\n\t\t\tdep = expr_eliminate_dups(expr_transform(dep));\n\t\t\tdep2 = expr_copy(basedep);\n\t\t\texpr_eliminate_eq(&dep, &dep2);\n\t\t\texpr_free(dep);\n\t\t\tif (!expr_is_yes(dep2)) {\n\t\t\t\texpr_free(dep2);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\texpr_free(dep2);\n\t\tnext:\n\t\t\tmenu_finalize(menu);\n\t\t\tmenu->parent = parent;\n\t\t\tlast_menu = menu;\n\t\t}\n\t\tif (last_menu) {\n\t\t\tparent->list = parent->next;\n\t\t\tparent->next = last_menu->next;\n\t\t\tlast_menu->next = NULL;\n\t\t}\n\n\t\tsym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);\n\t}\n\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\tif (sym && sym_is_choice(sym) &&\n\t\t    menu->sym && !sym_is_choice_value(menu->sym)) {\n\t\t\tcurrent_entry = menu;\n\t\t\tmenu->sym->flags |= SYMBOL_CHOICEVAL;\n\t\t\tif (!menu->prompt)\n\t\t\t\tmenu_warn(menu, \"choice value must have a prompt\");\n\t\t\tfor (prop = menu->sym->prop; prop; prop = prop->next) {\n\t\t\t\tif (prop->type == P_DEFAULT)\n\t\t\t\t\tprop_warn(prop, \"defaults for choice \"\n\t\t\t\t\t\t  \"values not supported\");\n\t\t\t\tif (prop->menu == menu)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (prop->type == P_PROMPT &&\n\t\t\t\t    prop->menu->parent->sym != sym)\n\t\t\t\t\tprop_warn(prop, \"choice value used outside its choice group\");\n\t\t\t}\n\t\t\t/* Non-tristate choice values of tristate choices must\n\t\t\t * depend on the choice being set to Y. The choice\n\t\t\t * values' dependencies were propagated to their\n\t\t\t * properties above, so the change here must be re-\n\t\t\t * propagated.\n\t\t\t */\n\t\t\tif (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {\n\t\t\t\tbasedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);\n\t\t\t\tmenu->dep = expr_alloc_and(basedep, menu->dep);\n\t\t\t\tfor (prop = menu->sym->prop; prop; prop = prop->next) {\n\t\t\t\t\tif (prop->menu != menu)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tprop->visible.expr = expr_alloc_and(expr_copy(basedep),\n\t\t\t\t\t\t\t\t\t    prop->visible.expr);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmenu_add_symbol(P_CHOICE, sym, NULL);\n\t\t\tprop = sym_get_choice_prop(sym);\n\t\t\tfor (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)\n\t\t\t\t;\n\t\t\t*ep = expr_alloc_one(E_LIST, NULL);\n\t\t\t(*ep)->right.sym = menu->sym;\n\t\t}\n\t\tif (menu->list && (!menu->prompt || !menu->prompt->text)) {\n\t\t\tfor (last_menu = menu->list; ; last_menu = last_menu->next) {\n\t\t\t\tlast_menu->parent = parent;\n\t\t\t\tif (!last_menu->next)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlast_menu->next = menu->next;\n\t\t\tmenu->next = menu->list;\n\t\t\tmenu->list = NULL;\n\t\t}\n\t}\n\n\tif (sym && !(sym->flags & SYMBOL_WARNED)) {\n\t\tif (sym->type == S_UNKNOWN)\n\t\t\tmenu_warn(parent, \"config symbol defined without type\");\n\n\t\tif (sym_is_choice(sym) && !parent->prompt)\n\t\t\tmenu_warn(parent, \"choice must have a prompt\");\n\n\t\t/* Check properties connected to this symbol */\n\t\tsym_check_prop(sym);\n\t\tsym->flags |= SYMBOL_WARNED;\n\t}\n\n\tif (sym && !sym_is_optional(sym) && parent->prompt) {\n\t\tsym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,\n\t\t\t\texpr_alloc_and(parent->prompt->visible.expr,\n\t\t\t\t\texpr_alloc_symbol(&symbol_mod)));\n\t}\n}\n\nbool menu_has_prompt(struct menu *menu)\n{\n\tif (!menu->prompt)\n\t\treturn false;\n\treturn true;\n}\n\n/*\n * Determine if a menu is empty.\n * A menu is considered empty if it contains no or only\n * invisible entries.\n */\nbool menu_is_empty(struct menu *menu)\n{\n\tstruct menu *child;\n\n\tfor (child = menu->list; child; child = child->next) {\n\t\tif (menu_is_visible(child))\n\t\t\treturn(false);\n\t}\n\treturn(true);\n}\n\nbool menu_is_visible(struct menu *menu)\n{\n\tstruct menu *child;\n\tstruct symbol *sym;\n\ttristate visible;\n\n\tif (!menu->prompt)\n\t\treturn false;\n\n\tif (menu->visibility) {\n\t\tif (expr_calc_value(menu->visibility) == no)\n\t\t\treturn no;\n\t}\n\n\tsym = menu->sym;\n\tif (sym) {\n\t\tsym_calc_value(sym);\n\t\tvisible = menu->prompt->visible.tri;\n\t} else\n\t\tvisible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);\n\n\tif (visible != no)\n\t\treturn true;\n\n\tif (!sym || sym_get_tristate_value(menu->sym) == no)\n\t\treturn false;\n\n\tfor (child = menu->list; child; child = child->next) {\n\t\tif (menu_is_visible(child)) {\n\t\t\tif (sym)\n\t\t\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nconst char *menu_get_prompt(struct menu *menu)\n{\n\tif (menu->prompt)\n\t\treturn menu->prompt->text;\n\telse if (menu->sym)\n\t\treturn menu->sym->name;\n\treturn NULL;\n}\n\nstruct menu *menu_get_root_menu(struct menu *menu)\n{\n\treturn &rootmenu;\n}\n\nstruct menu *menu_get_parent_menu(struct menu *menu)\n{\n\tenum prop_type type;\n\n\tfor (; menu != &rootmenu; menu = menu->parent) {\n\t\ttype = menu->prompt ? menu->prompt->type : 0;\n\t\tif (type == P_MENU)\n\t\t\tbreak;\n\t}\n\treturn menu;\n}\n\nbool menu_has_help(struct menu *menu)\n{\n\treturn menu->help != NULL;\n}\n\nconst char *menu_get_help(struct menu *menu)\n{\n\tif (menu->help)\n\t\treturn menu->help;\n\telse\n\t\treturn \"\";\n}\n\nstatic void get_prompt_str(struct gstr *r, struct property *prop,\n\t\t\t   struct list_head *head)\n{\n\tint i, j;\n\tstruct menu *submenu[8], *menu, *location = NULL;\n\tstruct jump_key *jump;\n\n\tstr_printf(r, _(\"Prompt: %s\\n\"), _(prop->text));\n\tmenu = prop->menu->parent;\n\tfor (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {\n\t\tbool accessible = menu_is_visible(menu);\n\n\t\tsubmenu[i++] = menu;\n\t\tif (location == NULL && accessible)\n\t\t\tlocation = menu;\n\t}\n\tif (head && location) {\n\t\tjump = xmalloc(sizeof(struct jump_key));\n\n\t\tif (menu_is_visible(prop->menu)) {\n\t\t\t/*\n\t\t\t * There is not enough room to put the hint at the\n\t\t\t * beginning of the \"Prompt\" line. Put the hint on the\n\t\t\t * last \"Location\" line even when it would belong on\n\t\t\t * the former.\n\t\t\t */\n\t\t\tjump->target = prop->menu;\n\t\t} else\n\t\t\tjump->target = location;\n\n\t\tif (list_empty(head))\n\t\t\tjump->index = 0;\n\t\telse\n\t\t\tjump->index = list_entry(head->prev, struct jump_key,\n\t\t\t\t\t\t entries)->index + 1;\n\n\t\tlist_add_tail(&jump->entries, head);\n\t}\n\n\tif (i > 0) {\n\t\tstr_printf(r, _(\"  Location:\\n\"));\n\t\tfor (j = 4; --i >= 0; j += 2) {\n\t\t\tmenu = submenu[i];\n\t\t\tif (head && location && menu == location)\n\t\t\t\tjump->offset = strlen(r->s);\n\t\t\tstr_printf(r, \"%*c-> %s\", j, ' ',\n\t\t\t\t   _(menu_get_prompt(menu)));\n\t\t\tif (menu->sym) {\n\t\t\t\tstr_printf(r, \" (%s [=%s])\", menu->sym->name ?\n\t\t\t\t\tmenu->sym->name : _(\"<choice>\"),\n\t\t\t\t\tsym_get_string_value(menu->sym));\n\t\t\t}\n\t\t\tstr_append(r, \"\\n\");\n\t\t}\n\t}\n}\n\n/*\n * get property of type P_SYMBOL\n */\nstatic struct property *get_symbol_prop(struct symbol *sym)\n{\n\tstruct property *prop = NULL;\n\n\tfor_all_properties(sym, prop, P_SYMBOL)\n\t\tbreak;\n\treturn prop;\n}\n\n/*\n * head is optional and may be NULL\n */\nvoid get_symbol_str(struct gstr *r, struct symbol *sym,\n\t\t    struct list_head *head)\n{\n\tbool hit;\n\tstruct property *prop;\n\n\tif (sym && sym->name) {\n\t\tstr_printf(r, \"Symbol: %s [=%s]\\n\", sym->name,\n\t\t\t   sym_get_string_value(sym));\n\t\tstr_printf(r, \"Type  : %s\\n\", sym_type_name(sym->type));\n\t\tif (sym->type == S_INT || sym->type == S_HEX) {\n\t\t\tprop = sym_get_range_prop(sym);\n\t\t\tif (prop) {\n\t\t\t\tstr_printf(r, \"Range : \");\n\t\t\t\texpr_gstr_print(prop->expr, r);\n\t\t\t\tstr_append(r, \"\\n\");\n\t\t\t}\n\t\t}\n\t}\n\tfor_all_prompts(sym, prop)\n\t\tget_prompt_str(r, prop, head);\n\n\tprop = get_symbol_prop(sym);\n\tif (prop) {\n\t\tstr_printf(r, _(\"  Defined at %s:%d\\n\"), prop->menu->file->name,\n\t\t\tprop->menu->lineno);\n\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\tstr_append(r, _(\"  Depends on: \"));\n\t\t\texpr_gstr_print(prop->visible.expr, r);\n\t\t\tstr_append(r, \"\\n\");\n\t\t}\n\t}\n\n\thit = false;\n\tfor_all_properties(sym, prop, P_SELECT) {\n\t\tif (!hit) {\n\t\t\tstr_append(r, \"  Selects: \");\n\t\t\thit = true;\n\t\t} else\n\t\t\tstr_printf(r, \" && \");\n\t\texpr_gstr_print(prop->expr, r);\n\t}\n\tif (hit)\n\t\tstr_append(r, \"\\n\");\n\tif (sym->rev_dep.expr) {\n\t\tstr_append(r, _(\"  Selected by: \"));\n\t\texpr_gstr_print(sym->rev_dep.expr, r);\n\t\tstr_append(r, \"\\n\");\n\t}\n\tstr_append(r, \"\\n\\n\");\n}\n\nstruct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)\n{\n\tstruct symbol *sym;\n\tstruct gstr res = str_new();\n\tint i;\n\n\tfor (i = 0; sym_arr && (sym = sym_arr[i]); i++)\n\t\tget_symbol_str(&res, sym, head);\n\tif (!i)\n\t\tstr_append(&res, _(\"No matches found.\\n\"));\n\treturn res;\n}\n\n\nvoid menu_get_ext_help(struct menu *menu, struct gstr *help)\n{\n\tstruct symbol *sym = menu->sym;\n\tconst char *help_text = nohelp_text;\n\n\tif (menu_has_help(menu)) {\n\t\tif (sym->name)\n\t\t\tstr_printf(help, \"%s%s:\\n\\n\", CONFIG_, sym->name);\n\t\thelp_text = menu_get_help(menu);\n\t}\n\tstr_printf(help, \"%s\\n\", _(help_text));\n\tif (sym)\n\t\tget_symbol_str(help, sym, NULL);\n}\n"
  },
  {
    "path": "kconfig/merge_config.sh",
    "content": "#!/bin/sh\n#  merge_config.sh - Takes a list of config fragment values, and merges\n#  them one by one. Provides warnings on overridden values, and specified\n#  values that did not make it to the resulting .config file (due to missed\n#  dependencies or config symbol removal).\n#\n#  Portions reused from kconf_check and generate_cfg:\n#  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check\n#  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg\n#\n#  Copyright (c) 2009-2010 Wind River Systems, Inc.\n#  Copyright 2011 Linaro\n#\n#  This program is free software; you can redistribute it and/or modify\n#  it under the terms of the GNU General Public License version 2 as\n#  published by the Free Software Foundation.\n#\n#  This program is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n#  See the GNU General Public License for more details.\n\nclean_up() {\n\trm -f $TMP_FILE\n\texit\n}\ntrap clean_up HUP INT TERM\n\nusage() {\n\techo \"Usage: $0 [OPTIONS] [CONFIG [...]]\"\n\techo \"  -h    display this help text\"\n\techo \"  -m    only merge the fragments, do not execute the make command\"\n\techo \"  -n    use allnoconfig instead of alldefconfig\"\n\techo \"  -r    list redundant entries when merging fragments\"\n\techo \"  -O    dir to put generated output files\"\n}\n\nMAKE=true\nALLTARGET=alldefconfig\nWARNREDUN=false\nOUTPUT=.\n\nwhile true; do\n\tcase $1 in\n\t\"-n\")\n\t\tALLTARGET=allnoconfig\n\t\tshift\n\t\tcontinue\n\t\t;;\n\t\"-m\")\n\t\tMAKE=false\n\t\tshift\n\t\tcontinue\n\t\t;;\n\t\"-h\")\n\t\tusage\n\t\texit\n\t\t;;\n\t\"-r\")\n\t\tWARNREDUN=true\n\t\tshift\n\t\tcontinue\n\t\t;;\n\t\"-O\")\n\t\tif [ -d $2 ];then\n\t\t\tOUTPUT=$(echo $2 | sed 's/\\/*$//')\n\t\telse\n\t\t\techo \"output directory $2 does not exist\" 1>&2\n\t\t\texit 1\n\t\tfi\n\t\tshift 2\n\t\tcontinue\n\t\t;;\n\t*)\n\t\tbreak\n\t\t;;\n\tesac\ndone\n\nINITFILE=$1\nshift;\n\nMERGE_LIST=$*\nSED_CONFIG_EXP=\"s/^\\(# \\)\\{0,1\\}\\(CONFIG_[a-zA-Z0-9_]*\\)[= ].*/\\2/p\"\nTMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)\n\necho \"Using $INITFILE as base\"\ncat $INITFILE > $TMP_FILE\n\n# Merge files, printing warnings on overrided values\nfor MERGE_FILE in $MERGE_LIST ; do\n\techo \"Merging $MERGE_FILE\"\n\tCFG_LIST=$(sed -n \"$SED_CONFIG_EXP\" $MERGE_FILE)\n\n\tfor CFG in $CFG_LIST ; do\n\t\tgrep -q -w $CFG $TMP_FILE\n\t\tif [ $? -eq 0 ] ; then\n\t\t\tPREV_VAL=$(grep -w $CFG $TMP_FILE)\n\t\t\tNEW_VAL=$(grep -w $CFG $MERGE_FILE)\n\t\t\tif [ \"x$PREV_VAL\" != \"x$NEW_VAL\" ] ; then\n\t\t\techo Value of $CFG is redefined by fragment $MERGE_FILE:\n\t\t\techo Previous  value: $PREV_VAL\n\t\t\techo New value:       $NEW_VAL\n\t\t\techo\n\t\t\telif [ \"$WARNREDUN\" = \"true\" ]; then\n\t\t\techo Value of $CFG is redundant by fragment $MERGE_FILE:\n\t\t\tfi\n\t\t\tsed -i \"/$CFG[ =]/d\" $TMP_FILE\n\t\tfi\n\tdone\n\tcat $MERGE_FILE >> $TMP_FILE\ndone\n\nif [ \"$MAKE\" = \"false\" ]; then\n\tcp $TMP_FILE $OUTPUT/.config\n\techo \"#\"\n\techo \"# merged configuration written to $OUTPUT/.config (needs make)\"\n\techo \"#\"\n\tclean_up\n\texit\nfi\n\n# If we have an output dir, setup the O= argument, otherwise leave\n# it blank, since O=. will create an unnecessary ./source softlink\nOUTPUT_ARG=\"\"\nif [ \"$OUTPUT\" != \".\" ] ; then\n\tOUTPUT_ARG=\"O=$OUTPUT\"\nfi\n\n\n# Use the merged file as the starting point for:\n# alldefconfig: Fills in any missing symbols with Kconfig default\n# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set\nmake KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET\n\n\n# Check all specified config values took (might have missed-dependency issues)\nfor CFG in $(sed -n \"$SED_CONFIG_EXP\" $TMP_FILE); do\n\n\tREQUESTED_VAL=$(grep -w -e \"$CFG\" $TMP_FILE)\n\tACTUAL_VAL=$(grep -w -e \"$CFG\" $OUTPUT/.config)\n\tif [ \"x$REQUESTED_VAL\" != \"x$ACTUAL_VAL\" ] ; then\n\t\techo \"Value requested for $CFG not in final .config\"\n\t\techo \"Requested value:  $REQUESTED_VAL\"\n\t\techo \"Actual value:     $ACTUAL_VAL\"\n\t\techo \"\"\n\tfi\ndone\n\nclean_up\n"
  },
  {
    "path": "kconfig/nconf.c",
    "content": "/*\n * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?\n * Released under the terms of the GNU GPL v2.0.\n *\n * Derived from menuconfig.\n *\n */\n#define _GNU_SOURCE\n#include <string.h>\n#include <stdlib.h>\n\n#include \"lkc.h\"\n#include \"nconf.h\"\n#include <ctype.h>\n\nstatic const char nconf_global_help[] = N_(\n\"Help windows\\n\"\n\"------------\\n\"\n\"o  Global help:  Unless in a data entry window, pressing <F1> will give \\n\"\n\"   you the global help window, which you are just reading.\\n\"\n\"\\n\"\n\"o  A short version of the global help is available by pressing <F3>.\\n\"\n\"\\n\"\n\"o  Local help:  To get help related to the current menu entry, use any\\n\"\n\"   of <?> <h>, or if in a data entry window then press <F1>.\\n\"\n\"\\n\"\n\"\\n\"\n\"Menu entries\\n\"\n\"------------\\n\"\n\"This interface lets you select features and parameters for the \\n\"\n\"build.  Features can either be built-in, modularized, or removed.\\n\"\n\"Parameters must be entered as text or decimal or hexadecimal numbers.\\n\"\n\"\\n\"\n\"Menu entries beginning with following braces represent features that\\n\"\n\"  [ ]  can be built in or removed\\n\"\n\"  < >  can be built in, modularized or removed\\n\"\n\"  { }  can be built in or modularized, are selected by another feature\\n\"\n\"  - -  are selected by another feature\\n\"\n\"  XXX  cannot be selected.  Symbol Info <F2> tells you why.\\n\"\n\"*, M or whitespace inside braces means to build in, build as a module\\n\"\n\"or to exclude the feature respectively.\\n\"\n\"\\n\"\n\"To change any of these features, highlight it with the movement keys\\n\"\n\"listed below and press <y> to build it in, <m> to make it a module or\\n\"\n\"<n> to remove it.  You may press the <Space> key to cycle through the\\n\"\n\"available options.\\n\"\n\"\\n\"\n\"A trailing \\\"--->\\\" designates a submenu, a trailing \\\"----\\\" an\\n\"\n\"empty submenu.\\n\"\n\"\\n\"\n\"Menu navigation keys\\n\"\n\"----------------------------------------------------------------------\\n\"\n\"Linewise up                 <Up>\\n\"\n\"Linewise down               <Down>\\n\"\n\"Pagewise up                 <Page Up>\\n\"\n\"Pagewise down               <Page Down>\\n\"\n\"First entry                 <Home>\\n\"\n\"Last entry                  <End>\\n\"\n\"Enter a submenu             <Right>  <Enter>\\n\"\n\"Go back to parent menu      <Left>   <Esc>  <F5>\\n\"\n\"Close a help window         <Enter>  <Esc>  <F5>\\n\"\n\"Close entry window, apply   <Enter>\\n\"\n\"Close entry window, forget  <Esc>  <F5>\\n\"\n\"Start incremental, case-insensitive search for STRING in menu entries,\\n\"\n\"    no regex support, STRING is displayed in upper left corner\\n\"\n\"                            </>STRING\\n\"\n\"    Remove last character   <Backspace>\\n\"\n\"    Jump to next hit        <Down>\\n\"\n\"    Jump to previous hit    <Up>\\n\"\n\"Exit menu search mode       </>  <Esc>\\n\"\n\"Search for configuration variables with or without leading CONFIG_\\n\"\n\"                            <F8>RegExpr<Enter>\\n\"\n\"Verbose search help         <F8><F1>\\n\"\n\"----------------------------------------------------------------------\\n\"\n\"\\n\"\n\"Unless in a data entry window, key <1> may be used instead of <F1>,\\n\"\n\"<2> instead of <F2>, etc.\\n\"\n\"\\n\"\n\"\\n\"\n\"Radiolist (Choice list)\\n\"\n\"-----------------------\\n\"\n\"Use the movement keys listed above to select the option you wish to set\\n\"\n\"and press <Space>.\\n\"\n\"\\n\"\n\"\\n\"\n\"Data entry\\n\"\n\"----------\\n\"\n\"Enter the requested information and press <Enter>.  Hexadecimal values\\n\"\n\"may be entered without the \\\"0x\\\" prefix.\\n\"\n\"\\n\"\n\"\\n\"\n\"Text Box (Help Window)\\n\"\n\"----------------------\\n\"\n\"Use movement keys as listed in table above.\\n\"\n\"\\n\"\n\"Press any of <Enter> <Esc> <q> <F5> <F9> to exit.\\n\"\n\"\\n\"\n\"\\n\"\n\"Alternate configuration files\\n\"\n\"-----------------------------\\n\"\n\"nconfig supports switching between different configurations.\\n\"\n\"Press <F6> to save your current configuration.  Press <F7> and enter\\n\"\n\"a file name to load a previously saved configuration.\\n\"\n\"\\n\"\n\"\\n\"\n\"Terminal configuration\\n\"\n\"----------------------\\n\"\n\"If you use nconfig in a xterm window, make sure your TERM environment\\n\"\n\"variable specifies a terminal configuration which supports at least\\n\"\n\"16 colors.  Otherwise nconfig will look rather bad.\\n\"\n\"\\n\"\n\"If the \\\"stty size\\\" command reports the current terminalsize correctly,\\n\"\n\"nconfig will adapt to sizes larger than the traditional 80x25 \\\"standard\\\"\\n\"\n\"and display longer menus properly.\\n\"\n\"\\n\"\n\"\\n\"\n\"Single menu mode\\n\"\n\"----------------\\n\"\n\"If you prefer to have all of the menu entries listed in a single menu,\\n\"\n\"rather than the default multimenu hierarchy, run nconfig with\\n\"\n\"NCONFIG_MODE environment variable set to single_menu.  Example:\\n\"\n\"\\n\"\n\"make NCONFIG_MODE=single_menu nconfig\\n\"\n\"\\n\"\n\"<Enter> will then unfold the appropriate category, or fold it if it\\n\"\n\"is already unfolded.  Folded menu entries will be designated by a\\n\"\n\"leading \\\"++>\\\" and unfolded entries by a leading \\\"-->\\\".\\n\"\n\"\\n\"\n\"Note that this mode can eventually be a little more CPU expensive than\\n\"\n\"the default mode, especially with a larger number of unfolded submenus.\\n\"\n\"\\n\"),\nmenu_no_f_instructions[] = N_(\n\"Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\\n\"\n\"Submenus are designated by a trailing \\\"--->\\\", empty ones by \\\"----\\\".\\n\"\n\"\\n\"\n\"Use the following keys to navigate the menus:\\n\"\n\"Move up or down with <Up> and <Down>.\\n\"\n\"Enter a submenu with <Enter> or <Right>.\\n\"\n\"Exit a submenu to its parent menu with <Esc> or <Left>.\\n\"\n\"Pressing <y> includes, <n> excludes, <m> modularizes features.\\n\"\n\"Pressing <Space> cycles through the available options.\\n\"\n\"To search for menu entries press </>.\\n\"\n\"<Esc> always leaves the current window.\\n\"\n\"\\n\"\n\"You do not have function keys support.\\n\"\n\"Press <1> instead of <F1>, <2> instead of <F2>, etc.\\n\"\n\"For verbose global help use key <1>.\\n\"\n\"For help related to the current menu entry press <?> or <h>.\\n\"),\nmenu_instructions[] = N_(\n\"Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\\n\"\n\"Submenus are designated by a trailing \\\"--->\\\", empty ones by \\\"----\\\".\\n\"\n\"\\n\"\n\"Use the following keys to navigate the menus:\\n\"\n\"Move up or down with <Up> or <Down>.\\n\"\n\"Enter a submenu with <Enter> or <Right>.\\n\"\n\"Exit a submenu to its parent menu with <Esc> or <Left>.\\n\"\n\"Pressing <y> includes, <n> excludes, <m> modularizes features.\\n\"\n\"Pressing <Space> cycles through the available options.\\n\"\n\"To search for menu entries press </>.\\n\"\n\"<Esc> always leaves the current window.\\n\"\n\"\\n\"\n\"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\\n\"\n\"For verbose global help press <F1>.\\n\"\n\"For help related to the current menu entry press <?> or <h>.\\n\"),\nradiolist_instructions[] = N_(\n\"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\\n\"\n\"with <Space>.\\n\"\n\"For help related to the current entry press <?> or <h>.\\n\"\n\"For global help press <F1>.\\n\"),\ninputbox_instructions_int[] = N_(\n\"Please enter a decimal value.\\n\"\n\"Fractions will not be accepted.\\n\"\n\"Press <Enter> to apply, <Esc> to cancel.\"),\ninputbox_instructions_hex[] = N_(\n\"Please enter a hexadecimal value.\\n\"\n\"Press <Enter> to apply, <Esc> to cancel.\"),\ninputbox_instructions_string[] = N_(\n\"Please enter a string value.\\n\"\n\"Press <Enter> to apply, <Esc> to cancel.\"),\nsetmod_text[] = N_(\n\"This feature depends on another feature which has been configured as a\\n\"\n\"module.  As a result, the current feature will be built as a module too.\"),\nload_config_text[] = N_(\n\"Enter the name of the configuration file you wish to load.\\n\"\n\"Accept the name shown to restore the configuration you last\\n\"\n\"retrieved.  Leave empty to abort.\"),\nload_config_help[] = N_(\n\"For various reasons, one may wish to keep several different\\n\"\n\"configurations available on a single machine.\\n\"\n\"\\n\"\n\"If you have saved a previous configuration in a file other than the\\n\"\n\"default one, entering its name here will allow you to load and modify\\n\"\n\"that configuration.\\n\"\n\"\\n\"\n\"Leave empty to abort.\\n\"),\nsave_config_text[] = N_(\n\"Enter a filename to which this configuration should be saved\\n\"\n\"as an alternate.  Leave empty to abort.\"),\nsave_config_help[] = N_(\n\"For various reasons, one may wish to keep several different\\n\"\n\"configurations available on a single machine.\\n\"\n\"\\n\"\n\"Entering a file name here will allow you to later retrieve, modify\\n\"\n\"and use the current configuration as an alternate to whatever\\n\"\n\"configuration options you have selected at that time.\\n\"\n\"\\n\"\n\"Leave empty to abort.\\n\"),\nsearch_help[] = N_(\n\"Search for symbols (configuration variable names CONFIG_*) and display\\n\"\n\"their relations.  Regular expressions are supported.\\n\"\n\"Example:  Search for \\\"^FOO\\\".\\n\"\n\"Result:\\n\"\n\"-----------------------------------------------------------------\\n\"\n\"Symbol: FOO [ = m]\\n\"\n\"Prompt: Foo bus is used to drive the bar HW\\n\"\n\"Defined at drivers/pci/Kconfig:47\\n\"\n\"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\\n\"\n\"Location:\\n\"\n\"  -> Bus options (PCI, PCMCIA, EISA, ISA)\\n\"\n\"    -> PCI support (PCI [ = y])\\n\"\n\"      -> PCI access mode (<choice> [ = y])\\n\"\n\"Selects: LIBCRC32\\n\"\n\"Selected by: BAR\\n\"\n\"-----------------------------------------------------------------\\n\"\n\"o  The line 'Prompt:' shows the text displayed for this symbol in\\n\"\n\"   the menu hierarchy.\\n\"\n\"o  The 'Defined at' line tells at what file / line number the symbol is\\n\"\n\"   defined.\\n\"\n\"o  The 'Depends on:' line lists symbols that need to be defined for\\n\"\n\"   this symbol to be visible and selectable in the menu.\\n\"\n\"o  The 'Location:' lines tell, where in the menu structure this symbol\\n\"\n\"   is located.  A location followed by a [ = y] indicates that this is\\n\"\n\"   a selectable menu item, and the current value is displayed inside\\n\"\n\"   brackets.\\n\"\n\"o  The 'Selects:' line tells, what symbol will be automatically selected\\n\"\n\"   if this symbol is selected (y or m).\\n\"\n\"o  The 'Selected by' line tells what symbol has selected this symbol.\\n\"\n\"\\n\"\n\"Only relevant lines are shown.\\n\"\n\"\\n\\n\"\n\"Search examples:\\n\"\n\"USB  => find all symbols containing USB\\n\"\n\"^USB => find all symbols starting with USB\\n\"\n\"USB$ => find all symbols ending with USB\\n\"\n\"\\n\");\n\nstruct mitem {\n\tchar str[256];\n\tchar tag;\n\tvoid *usrptr;\n\tint is_visible;\n};\n\n#define MAX_MENU_ITEMS 4096\nstatic int show_all_items;\nstatic int indent;\nstatic struct menu *current_menu;\nstatic int child_count;\nstatic int single_menu_mode;\n/* the window in which all information appears */\nstatic WINDOW *main_window;\n/* the largest size of the menu window */\nstatic int mwin_max_lines;\nstatic int mwin_max_cols;\n/* the window in which we show option buttons */\nstatic MENU *curses_menu;\nstatic ITEM *curses_menu_items[MAX_MENU_ITEMS];\nstatic struct mitem k_menu_items[MAX_MENU_ITEMS];\nstatic int items_num;\nstatic int global_exit;\n/* the currently selected button */\nconst char *current_instructions = menu_instructions;\n\nstatic char *dialog_input_result;\nstatic int dialog_input_result_len;\n\nstatic void conf(struct menu *menu);\nstatic void conf_choice(struct menu *menu);\nstatic void conf_string(struct menu *menu);\nstatic void conf_load(void);\nstatic void conf_save(void);\nstatic void show_help(struct menu *menu);\nstatic int do_exit(void);\nstatic void setup_windows(void);\nstatic void search_conf(void);\n\ntypedef void (*function_key_handler_t)(int *key, struct menu *menu);\nstatic void handle_f1(int *key, struct menu *current_item);\nstatic void handle_f2(int *key, struct menu *current_item);\nstatic void handle_f3(int *key, struct menu *current_item);\nstatic void handle_f4(int *key, struct menu *current_item);\nstatic void handle_f5(int *key, struct menu *current_item);\nstatic void handle_f6(int *key, struct menu *current_item);\nstatic void handle_f7(int *key, struct menu *current_item);\nstatic void handle_f8(int *key, struct menu *current_item);\nstatic void handle_f9(int *key, struct menu *current_item);\n\nstruct function_keys {\n\tconst char *key_str;\n\tconst char *func;\n\tfunction_key key;\n\tfunction_key_handler_t handler;\n};\n\nstatic const int function_keys_num = 9;\nstruct function_keys function_keys[] = {\n\t{\n\t\t.key_str = \"F1\",\n\t\t.func = \"Help\",\n\t\t.key = F_HELP,\n\t\t.handler = handle_f1,\n\t},\n\t{\n\t\t.key_str = \"F2\",\n\t\t.func = \"SymInfo\",\n\t\t.key = F_SYMBOL,\n\t\t.handler = handle_f2,\n\t},\n\t{\n\t\t.key_str = \"F3\",\n\t\t.func = \"Help 2\",\n\t\t.key = F_INSTS,\n\t\t.handler = handle_f3,\n\t},\n\t{\n\t\t.key_str = \"F4\",\n\t\t.func = \"ShowAll\",\n\t\t.key = F_CONF,\n\t\t.handler = handle_f4,\n\t},\n\t{\n\t\t.key_str = \"F5\",\n\t\t.func = \"Back\",\n\t\t.key = F_BACK,\n\t\t.handler = handle_f5,\n\t},\n\t{\n\t\t.key_str = \"F6\",\n\t\t.func = \"Save\",\n\t\t.key = F_SAVE,\n\t\t.handler = handle_f6,\n\t},\n\t{\n\t\t.key_str = \"F7\",\n\t\t.func = \"Load\",\n\t\t.key = F_LOAD,\n\t\t.handler = handle_f7,\n\t},\n\t{\n\t\t.key_str = \"F8\",\n\t\t.func = \"SymSearch\",\n\t\t.key = F_SEARCH,\n\t\t.handler = handle_f8,\n\t},\n\t{\n\t\t.key_str = \"F9\",\n\t\t.func = \"Exit\",\n\t\t.key = F_EXIT,\n\t\t.handler = handle_f9,\n\t},\n};\n\nstatic void print_function_line(void)\n{\n\tint i;\n\tint offset = 1;\n\tconst int skip = 1;\n\tint lines = getmaxy(stdscr);\n\n\tfor (i = 0; i < function_keys_num; i++) {\n\t\t(void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);\n\t\tmvwprintw(main_window, lines-3, offset,\n\t\t\t\t\"%s\",\n\t\t\t\tfunction_keys[i].key_str);\n\t\t(void) wattrset(main_window, attributes[FUNCTION_TEXT]);\n\t\toffset += strlen(function_keys[i].key_str);\n\t\tmvwprintw(main_window, lines-3,\n\t\t\t\toffset, \"%s\",\n\t\t\t\tfunction_keys[i].func);\n\t\toffset += strlen(function_keys[i].func) + skip;\n\t}\n\t(void) wattrset(main_window, attributes[NORMAL]);\n}\n\n/* help */\nstatic void handle_f1(int *key, struct menu *current_item)\n{\n\tshow_scroll_win(main_window,\n\t\t\t_(\"Global help\"), _(nconf_global_help));\n\treturn;\n}\n\n/* symbole help */\nstatic void handle_f2(int *key, struct menu *current_item)\n{\n\tshow_help(current_item);\n\treturn;\n}\n\n/* instructions */\nstatic void handle_f3(int *key, struct menu *current_item)\n{\n\tshow_scroll_win(main_window,\n\t\t\t_(\"Short help\"),\n\t\t\t_(current_instructions));\n\treturn;\n}\n\n/* config */\nstatic void handle_f4(int *key, struct menu *current_item)\n{\n\tint res = btn_dialog(main_window,\n\t\t\t_(\"Show all symbols?\"),\n\t\t\t2,\n\t\t\t\"   <Show All>   \",\n\t\t\t\"<Don't show all>\");\n\tif (res == 0)\n\t\tshow_all_items = 1;\n\telse if (res == 1)\n\t\tshow_all_items = 0;\n\n\treturn;\n}\n\n/* back */\nstatic void handle_f5(int *key, struct menu *current_item)\n{\n\t*key = KEY_LEFT;\n\treturn;\n}\n\n/* save */\nstatic void handle_f6(int *key, struct menu *current_item)\n{\n\tconf_save();\n\treturn;\n}\n\n/* load */\nstatic void handle_f7(int *key, struct menu *current_item)\n{\n\tconf_load();\n\treturn;\n}\n\n/* search */\nstatic void handle_f8(int *key, struct menu *current_item)\n{\n\tsearch_conf();\n\treturn;\n}\n\n/* exit */\nstatic void handle_f9(int *key, struct menu *current_item)\n{\n\tdo_exit();\n\treturn;\n}\n\n/* return != 0 to indicate the key was handles */\nstatic int process_special_keys(int *key, struct menu *menu)\n{\n\tint i;\n\n\tif (*key == KEY_RESIZE) {\n\t\tsetup_windows();\n\t\treturn 1;\n\t}\n\n\tfor (i = 0; i < function_keys_num; i++) {\n\t\tif (*key == KEY_F(function_keys[i].key) ||\n\t\t    *key == '0' + function_keys[i].key){\n\t\t\tfunction_keys[i].handler(key, menu);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic void clean_items(void)\n{\n\tint i;\n\tfor (i = 0; curses_menu_items[i]; i++)\n\t\tfree_item(curses_menu_items[i]);\n\tbzero(curses_menu_items, sizeof(curses_menu_items));\n\tbzero(k_menu_items, sizeof(k_menu_items));\n\titems_num = 0;\n}\n\ntypedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,\n\tFIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;\n\n/* return the index of the matched item, or -1 if no such item exists */\nstatic int get_mext_match(const char *match_str, match_f flag)\n{\n\tint match_start = item_index(current_item(curses_menu));\n\tint index;\n\n\tif (flag == FIND_NEXT_MATCH_DOWN)\n\t\t++match_start;\n\telse if (flag == FIND_NEXT_MATCH_UP)\n\t\t--match_start;\n\n\tindex = match_start;\n\tindex = (index + items_num) % items_num;\n\twhile (true) {\n\t\tchar *str = k_menu_items[index].str;\n\t\tif (strcasestr(str, match_str) != 0)\n\t\t\treturn index;\n\t\tif (flag == FIND_NEXT_MATCH_UP ||\n\t\t    flag == MATCH_TINKER_PATTERN_UP)\n\t\t\t--index;\n\t\telse\n\t\t\t++index;\n\t\tindex = (index + items_num) % items_num;\n\t\tif (index == match_start)\n\t\t\treturn -1;\n\t}\n}\n\n/* Make a new item. */\nstatic void item_make(struct menu *menu, char tag, const char *fmt, ...)\n{\n\tva_list ap;\n\n\tif (items_num > MAX_MENU_ITEMS-1)\n\t\treturn;\n\n\tbzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));\n\tk_menu_items[items_num].tag = tag;\n\tk_menu_items[items_num].usrptr = menu;\n\tif (menu != NULL)\n\t\tk_menu_items[items_num].is_visible =\n\t\t\tmenu_is_visible(menu);\n\telse\n\t\tk_menu_items[items_num].is_visible = 1;\n\n\tva_start(ap, fmt);\n\tvsnprintf(k_menu_items[items_num].str,\n\t\t  sizeof(k_menu_items[items_num].str),\n\t\t  fmt, ap);\n\tva_end(ap);\n\n\tif (!k_menu_items[items_num].is_visible)\n\t\tmemcpy(k_menu_items[items_num].str, \"XXX\", 3);\n\n\tcurses_menu_items[items_num] = new_item(\n\t\t\tk_menu_items[items_num].str,\n\t\t\tk_menu_items[items_num].str);\n\tset_item_userptr(curses_menu_items[items_num],\n\t\t\t&k_menu_items[items_num]);\n\t/*\n\tif (!k_menu_items[items_num].is_visible)\n\t\titem_opts_off(curses_menu_items[items_num], O_SELECTABLE);\n\t*/\n\n\titems_num++;\n\tcurses_menu_items[items_num] = NULL;\n}\n\n/* very hackish. adds a string to the last item added */\nstatic void item_add_str(const char *fmt, ...)\n{\n\tva_list ap;\n\tint index = items_num-1;\n\tchar new_str[256];\n\tchar tmp_str[256];\n\n\tif (index < 0)\n\t\treturn;\n\n\tva_start(ap, fmt);\n\tvsnprintf(new_str, sizeof(new_str), fmt, ap);\n\tva_end(ap);\n\tsnprintf(tmp_str, sizeof(tmp_str), \"%s%s\",\n\t\t\tk_menu_items[index].str, new_str);\n\tstrncpy(k_menu_items[index].str,\n\t\ttmp_str,\n\t\tsizeof(k_menu_items[index].str));\n\n\tfree_item(curses_menu_items[index]);\n\tcurses_menu_items[index] = new_item(\n\t\t\tk_menu_items[index].str,\n\t\t\tk_menu_items[index].str);\n\tset_item_userptr(curses_menu_items[index],\n\t\t\t&k_menu_items[index]);\n}\n\n/* get the tag of the currently selected item */\nstatic char item_tag(void)\n{\n\tITEM *cur;\n\tstruct mitem *mcur;\n\n\tcur = current_item(curses_menu);\n\tif (cur == NULL)\n\t\treturn 0;\n\tmcur = (struct mitem *) item_userptr(cur);\n\treturn mcur->tag;\n}\n\nstatic int curses_item_index(void)\n{\n\treturn  item_index(current_item(curses_menu));\n}\n\nstatic void *item_data(void)\n{\n\tITEM *cur;\n\tstruct mitem *mcur;\n\n\tcur = current_item(curses_menu);\n\tif (!cur)\n\t\treturn NULL;\n\tmcur = (struct mitem *) item_userptr(cur);\n\treturn mcur->usrptr;\n\n}\n\nstatic int item_is_tag(char tag)\n{\n\treturn item_tag() == tag;\n}\n\nstatic char filename[PATH_MAX+1];\nstatic char menu_backtitle[PATH_MAX+128];\nstatic const char *set_config_filename(const char *config_filename)\n{\n\tint size;\n\n\tsize = snprintf(menu_backtitle, sizeof(menu_backtitle),\n\t\t\t\"%s - %s\", config_filename, rootmenu.prompt->text);\n\tif (size >= sizeof(menu_backtitle))\n\t\tmenu_backtitle[sizeof(menu_backtitle)-1] = '\\0';\n\n\tsize = snprintf(filename, sizeof(filename), \"%s\", config_filename);\n\tif (size >= sizeof(filename))\n\t\tfilename[sizeof(filename)-1] = '\\0';\n\treturn menu_backtitle;\n}\n\n/* return = 0 means we are successful.\n * -1 means go on doing what you were doing\n */\nstatic int do_exit(void)\n{\n\tint res;\n\tif (!conf_get_changed()) {\n\t\tglobal_exit = 1;\n\t\treturn 0;\n\t}\n\tres = btn_dialog(main_window,\n\t\t\t_(\"Do you wish to save your new configuration?\\n\"\n\t\t\t\t\"<ESC> to cancel and resume nconfig.\"),\n\t\t\t2,\n\t\t\t\"   <save>   \",\n\t\t\t\"<don't save>\");\n\tif (res == KEY_EXIT) {\n\t\tglobal_exit = 0;\n\t\treturn -1;\n\t}\n\n\t/* if we got here, the user really wants to exit */\n\tswitch (res) {\n\tcase 0:\n\t\tres = conf_write(filename);\n\t\tif (res)\n\t\t\tbtn_dialog(\n\t\t\t\tmain_window,\n\t\t\t\t_(\"Error during writing of configuration.\\n\"\n\t\t\t\t  \"Your configuration changes were NOT saved.\"),\n\t\t\t\t  1,\n\t\t\t\t  \"<OK>\");\n\t\tbreak;\n\tdefault:\n\t\tbtn_dialog(\n\t\t\tmain_window,\n\t\t\t_(\"Your configuration changes were NOT saved.\"),\n\t\t\t1,\n\t\t\t\"<OK>\");\n\t\tbreak;\n\t}\n\tglobal_exit = 1;\n\treturn 0;\n}\n\n\nstatic void search_conf(void)\n{\n\tstruct symbol **sym_arr;\n\tstruct gstr res;\n\tstruct gstr title;\n\tchar *dialog_input;\n\tint dres;\n\n\ttitle = str_new();\n\tstr_printf( &title, _(\"Enter (sub)string or regexp to search for \"\n\t\t\t      \"(with or without \\\"%s\\\")\"), CONFIG_);\n\nagain:\n\tdres = dialog_inputbox(main_window,\n\t\t\t_(\"Search Configuration Parameter\"),\n\t\t\tstr_get(&title),\n\t\t\t\"\", &dialog_input_result, &dialog_input_result_len);\n\tswitch (dres) {\n\tcase 0:\n\t\tbreak;\n\tcase 1:\n\t\tshow_scroll_win(main_window,\n\t\t\t\t_(\"Search Configuration\"), search_help);\n\t\tgoto again;\n\tdefault:\n\t\tstr_free(&title);\n\t\treturn;\n\t}\n\n\t/* strip the prefix if necessary */\n\tdialog_input = dialog_input_result;\n\tif (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)\n\t\tdialog_input += strlen(CONFIG_);\n\n\tsym_arr = sym_re_search(dialog_input);\n\tres = get_relations_str(sym_arr, NULL);\n\tfree(sym_arr);\n\tshow_scroll_win(main_window,\n\t\t\t_(\"Search Results\"), str_get(&res));\n\tstr_free(&res);\n\tstr_free(&title);\n}\n\n\nstatic void build_conf(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct menu *child;\n\tint type, tmp, doint = 2;\n\ttristate val;\n\tchar ch;\n\n\tif (!menu || (!show_all_items && !menu_is_visible(menu)))\n\t\treturn;\n\n\tsym = menu->sym;\n\tprop = menu->prompt;\n\tif (!sym) {\n\t\tif (prop && menu != current_menu) {\n\t\t\tconst char *prompt = menu_get_prompt(menu);\n\t\t\tenum prop_type ptype;\n\t\t\tptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\t\t\tswitch (ptype) {\n\t\t\tcase P_MENU:\n\t\t\t\tchild_count++;\n\t\t\t\tprompt = _(prompt);\n\t\t\t\tif (single_menu_mode) {\n\t\t\t\t\titem_make(menu, 'm',\n\t\t\t\t\t\t\"%s%*c%s\",\n\t\t\t\t\t\tmenu->data ? \"-->\" : \"++>\",\n\t\t\t\t\t\tindent + 1, ' ', prompt);\n\t\t\t\t} else\n\t\t\t\t\titem_make(menu, 'm',\n\t\t\t\t\t\t  \"   %*c%s  %s\",\n\t\t\t\t\t\t  indent + 1, ' ', prompt,\n\t\t\t\t\t\t  menu_is_empty(menu) ? \"----\" : \"--->\");\n\n\t\t\t\tif (single_menu_mode && menu->data)\n\t\t\t\t\tgoto conf_childs;\n\t\t\t\treturn;\n\t\t\tcase P_COMMENT:\n\t\t\t\tif (prompt) {\n\t\t\t\t\tchild_count++;\n\t\t\t\t\titem_make(menu, ':',\n\t\t\t\t\t\t\"   %*c*** %s ***\",\n\t\t\t\t\t\tindent + 1, ' ',\n\t\t\t\t\t\t_(prompt));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (prompt) {\n\t\t\t\t\tchild_count++;\n\t\t\t\t\titem_make(menu, ':', \"---%*c%s\",\n\t\t\t\t\t\tindent + 1, ' ',\n\t\t\t\t\t\t_(prompt));\n\t\t\t\t}\n\t\t\t}\n\t\t} else\n\t\t\tdoint = 0;\n\t\tgoto conf_childs;\n\t}\n\n\ttype = sym_get_type(sym);\n\tif (sym_is_choice(sym)) {\n\t\tstruct symbol *def_sym = sym_get_choice_value(sym);\n\t\tstruct menu *def_menu = NULL;\n\n\t\tchild_count++;\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (menu_is_visible(child) && child->sym == def_sym)\n\t\t\t\tdef_menu = child;\n\t\t}\n\n\t\tval = sym_get_tristate_value(sym);\n\t\tif (sym_is_changable(sym)) {\n\t\t\tswitch (type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\t\titem_make(menu, 't', \"[%c]\",\n\t\t\t\t\t\tval == no ? ' ' : '*');\n\t\t\t\tbreak;\n\t\t\tcase S_TRISTATE:\n\t\t\t\tswitch (val) {\n\t\t\t\tcase yes:\n\t\t\t\t\tch = '*';\n\t\t\t\t\tbreak;\n\t\t\t\tcase mod:\n\t\t\t\t\tch = 'M';\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tch = ' ';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\titem_make(menu, 't', \"<%c>\", ch);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\titem_make(menu, def_menu ? 't' : ':', \"   \");\n\t\t}\n\n\t\titem_add_str(\"%*c%s\", indent + 1,\n\t\t\t\t' ', _(menu_get_prompt(menu)));\n\t\tif (val == yes) {\n\t\t\tif (def_menu) {\n\t\t\t\titem_add_str(\" (%s)\",\n\t\t\t\t\t_(menu_get_prompt(def_menu)));\n\t\t\t\titem_add_str(\"  --->\");\n\t\t\t\tif (def_menu->list) {\n\t\t\t\t\tindent += 2;\n\t\t\t\t\tbuild_conf(def_menu);\n\t\t\t\t\tindent -= 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tif (menu == current_menu) {\n\t\t\titem_make(menu, ':',\n\t\t\t\t\"---%*c%s\", indent + 1,\n\t\t\t\t' ', _(menu_get_prompt(menu)));\n\t\t\tgoto conf_childs;\n\t\t}\n\t\tchild_count++;\n\t\tval = sym_get_tristate_value(sym);\n\t\tif (sym_is_choice_value(sym) && val == yes) {\n\t\t\titem_make(menu, ':', \"   \");\n\t\t} else {\n\t\t\tswitch (type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\t\tif (sym_is_changable(sym))\n\t\t\t\t\titem_make(menu, 't', \"[%c]\",\n\t\t\t\t\t\tval == no ? ' ' : '*');\n\t\t\t\telse\n\t\t\t\t\titem_make(menu, 't', \"-%c-\",\n\t\t\t\t\t\tval == no ? ' ' : '*');\n\t\t\t\tbreak;\n\t\t\tcase S_TRISTATE:\n\t\t\t\tswitch (val) {\n\t\t\t\tcase yes:\n\t\t\t\t\tch = '*';\n\t\t\t\t\tbreak;\n\t\t\t\tcase mod:\n\t\t\t\t\tch = 'M';\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tch = ' ';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (sym_is_changable(sym)) {\n\t\t\t\t\tif (sym->rev_dep.tri == mod)\n\t\t\t\t\t\titem_make(menu,\n\t\t\t\t\t\t\t't', \"{%c}\", ch);\n\t\t\t\t\telse\n\t\t\t\t\t\titem_make(menu,\n\t\t\t\t\t\t\t't', \"<%c>\", ch);\n\t\t\t\t} else\n\t\t\t\t\titem_make(menu, 't', \"-%c-\", ch);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\ttmp = 2 + strlen(sym_get_string_value(sym));\n\t\t\t\titem_make(menu, 's', \"    (%s)\",\n\t\t\t\t\t\tsym_get_string_value(sym));\n\t\t\t\ttmp = indent - tmp + 4;\n\t\t\t\tif (tmp < 0)\n\t\t\t\t\ttmp = 0;\n\t\t\t\titem_add_str(\"%*c%s%s\", tmp, ' ',\n\t\t\t\t\t\t_(menu_get_prompt(menu)),\n\t\t\t\t\t\t(sym_has_value(sym) ||\n\t\t\t\t\t\t !sym_is_changable(sym)) ? \"\" :\n\t\t\t\t\t\t_(\" (NEW)\"));\n\t\t\t\tgoto conf_childs;\n\t\t\t}\n\t\t}\n\t\titem_add_str(\"%*c%s%s\", indent + 1, ' ',\n\t\t\t\t_(menu_get_prompt(menu)),\n\t\t\t\t(sym_has_value(sym) || !sym_is_changable(sym)) ?\n\t\t\t\t\"\" : _(\" (NEW)\"));\n\t\tif (menu->prompt && menu->prompt->type == P_MENU) {\n\t\t\titem_add_str(\"  %s\", menu_is_empty(menu) ? \"----\" : \"--->\");\n\t\t\treturn;\n\t\t}\n\t}\n\nconf_childs:\n\tindent += doint;\n\tfor (child = menu->list; child; child = child->next)\n\t\tbuild_conf(child);\n\tindent -= doint;\n}\n\nstatic void reset_menu(void)\n{\n\tunpost_menu(curses_menu);\n\tclean_items();\n}\n\n/* adjust the menu to show this item.\n * prefer not to scroll the menu if possible*/\nstatic void center_item(int selected_index, int *last_top_row)\n{\n\tint toprow;\n\n\tset_top_row(curses_menu, *last_top_row);\n\ttoprow = top_row(curses_menu);\n\tif (selected_index < toprow ||\n\t    selected_index >= toprow+mwin_max_lines) {\n\t\ttoprow = max(selected_index-mwin_max_lines/2, 0);\n\t\tif (toprow >= item_count(curses_menu)-mwin_max_lines)\n\t\t\ttoprow = item_count(curses_menu)-mwin_max_lines;\n\t\tset_top_row(curses_menu, toprow);\n\t}\n\tset_current_item(curses_menu,\n\t\t\tcurses_menu_items[selected_index]);\n\t*last_top_row = toprow;\n\tpost_menu(curses_menu);\n\trefresh_all_windows(main_window);\n}\n\n/* this function assumes reset_menu has been called before */\nstatic void show_menu(const char *prompt, const char *instructions,\n\t\tint selected_index, int *last_top_row)\n{\n\tint maxx, maxy;\n\tWINDOW *menu_window;\n\n\tcurrent_instructions = instructions;\n\n\tclear();\n\t(void) wattrset(main_window, attributes[NORMAL]);\n\tprint_in_middle(stdscr, 1, 0, getmaxx(stdscr),\n\t\t\tmenu_backtitle,\n\t\t\tattributes[MAIN_HEADING]);\n\n\t(void) wattrset(main_window, attributes[MAIN_MENU_BOX]);\n\tbox(main_window, 0, 0);\n\t(void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);\n\tmvwprintw(main_window, 0, 3, \" %s \", prompt);\n\t(void) wattrset(main_window, attributes[NORMAL]);\n\n\tset_menu_items(curses_menu, curses_menu_items);\n\n\t/* position the menu at the middle of the screen */\n\tscale_menu(curses_menu, &maxy, &maxx);\n\tmaxx = min(maxx, mwin_max_cols-2);\n\tmaxy = mwin_max_lines;\n\tmenu_window = derwin(main_window,\n\t\t\tmaxy,\n\t\t\tmaxx,\n\t\t\t2,\n\t\t\t(mwin_max_cols-maxx)/2);\n\tkeypad(menu_window, TRUE);\n\tset_menu_win(curses_menu, menu_window);\n\tset_menu_sub(curses_menu, menu_window);\n\n\t/* must reassert this after changing items, otherwise returns to a\n\t * default of 16\n\t */\n\tset_menu_format(curses_menu, maxy, 1);\n\tcenter_item(selected_index, last_top_row);\n\tset_menu_format(curses_menu, maxy, 1);\n\n\tprint_function_line();\n\n\t/* Post the menu */\n\tpost_menu(curses_menu);\n\trefresh_all_windows(main_window);\n}\n\nstatic void adj_match_dir(match_f *match_direction)\n{\n\tif (*match_direction == FIND_NEXT_MATCH_DOWN)\n\t\t*match_direction =\n\t\t\tMATCH_TINKER_PATTERN_DOWN;\n\telse if (*match_direction == FIND_NEXT_MATCH_UP)\n\t\t*match_direction =\n\t\t\tMATCH_TINKER_PATTERN_UP;\n\t/* else, do no change.. */\n}\n\nstruct match_state\n{\n\tint in_search;\n\tmatch_f match_direction;\n\tchar pattern[256];\n};\n\n/* Return 0 means I have handled the key. In such a case, ans should hold the\n * item to center, or -1 otherwise.\n * Else return -1 .\n */\nstatic int do_match(int key, struct match_state *state, int *ans)\n{\n\tchar c = (char) key;\n\tint terminate_search = 0;\n\t*ans = -1;\n\tif (key == '/' || (state->in_search && key == 27)) {\n\t\tmove(0, 0);\n\t\trefresh();\n\t\tclrtoeol();\n\t\tstate->in_search = 1-state->in_search;\n\t\tbzero(state->pattern, sizeof(state->pattern));\n\t\tstate->match_direction = MATCH_TINKER_PATTERN_DOWN;\n\t\treturn 0;\n\t} else if (!state->in_search)\n\t\treturn 1;\n\n\tif (isalnum(c) || isgraph(c) || c == ' ') {\n\t\tstate->pattern[strlen(state->pattern)] = c;\n\t\tstate->pattern[strlen(state->pattern)] = '\\0';\n\t\tadj_match_dir(&state->match_direction);\n\t\t*ans = get_mext_match(state->pattern,\n\t\t\t\tstate->match_direction);\n\t} else if (key == KEY_DOWN) {\n\t\tstate->match_direction = FIND_NEXT_MATCH_DOWN;\n\t\t*ans = get_mext_match(state->pattern,\n\t\t\t\tstate->match_direction);\n\t} else if (key == KEY_UP) {\n\t\tstate->match_direction = FIND_NEXT_MATCH_UP;\n\t\t*ans = get_mext_match(state->pattern,\n\t\t\t\tstate->match_direction);\n\t} else if (key == KEY_BACKSPACE || key == 127) {\n\t\tstate->pattern[strlen(state->pattern)-1] = '\\0';\n\t\tadj_match_dir(&state->match_direction);\n\t} else\n\t\tterminate_search = 1;\n\n\tif (terminate_search) {\n\t\tstate->in_search = 0;\n\t\tbzero(state->pattern, sizeof(state->pattern));\n\t\tmove(0, 0);\n\t\trefresh();\n\t\tclrtoeol();\n\t\treturn -1;\n\t}\n\treturn 0;\n}\n\nstatic void conf(struct menu *menu)\n{\n\tstruct menu *submenu = 0;\n\tconst char *prompt = menu_get_prompt(menu);\n\tstruct symbol *sym;\n\tint res;\n\tint current_index = 0;\n\tint last_top_row = 0;\n\tstruct match_state match_state = {\n\t\t.in_search = 0,\n\t\t.match_direction = MATCH_TINKER_PATTERN_DOWN,\n\t\t.pattern = \"\",\n\t};\n\n\twhile (!global_exit) {\n\t\treset_menu();\n\t\tcurrent_menu = menu;\n\t\tbuild_conf(menu);\n\t\tif (!child_count)\n\t\t\tbreak;\n\n\t\tshow_menu(prompt ? _(prompt) : _(\"Main Menu\"),\n\t\t\t\t_(menu_instructions),\n\t\t\t\tcurrent_index, &last_top_row);\n\t\tkeypad((menu_win(curses_menu)), TRUE);\n\t\twhile (!global_exit) {\n\t\t\tif (match_state.in_search) {\n\t\t\t\tmvprintw(0, 0,\n\t\t\t\t\t\"searching: %s\", match_state.pattern);\n\t\t\t\tclrtoeol();\n\t\t\t}\n\t\t\trefresh_all_windows(main_window);\n\t\t\tres = wgetch(menu_win(curses_menu));\n\t\t\tif (!res)\n\t\t\t\tbreak;\n\t\t\tif (do_match(res, &match_state, &current_index) == 0) {\n\t\t\t\tif (current_index != -1)\n\t\t\t\t\tcenter_item(current_index,\n\t\t\t\t\t\t    &last_top_row);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (process_special_keys(&res,\n\t\t\t\t\t\t(struct menu *) item_data()))\n\t\t\t\tbreak;\n\t\t\tswitch (res) {\n\t\t\tcase KEY_DOWN:\n\t\t\t\tmenu_driver(curses_menu, REQ_DOWN_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_UP:\n\t\t\t\tmenu_driver(curses_menu, REQ_UP_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_NPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_DPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_PPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_UPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_HOME:\n\t\t\t\tmenu_driver(curses_menu, REQ_FIRST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_END:\n\t\t\t\tmenu_driver(curses_menu, REQ_LAST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\tcase '?':\n\t\t\t\tshow_help((struct menu *) item_data());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (res == 10 || res == 27 ||\n\t\t\t\tres == 32 || res == 'n' || res == 'y' ||\n\t\t\t\tres == KEY_LEFT || res == KEY_RIGHT ||\n\t\t\t\tres == 'm')\n\t\t\t\tbreak;\n\t\t\trefresh_all_windows(main_window);\n\t\t}\n\n\t\trefresh_all_windows(main_window);\n\t\t/* if ESC or left*/\n\t\tif (res == 27 || (menu != &rootmenu && res == KEY_LEFT))\n\t\t\tbreak;\n\n\t\t/* remember location in the menu */\n\t\tlast_top_row = top_row(curses_menu);\n\t\tcurrent_index = curses_item_index();\n\n\t\tif (!item_tag())\n\t\t\tcontinue;\n\n\t\tsubmenu = (struct menu *) item_data();\n\t\tif (!submenu || !menu_is_visible(submenu))\n\t\t\tcontinue;\n\t\tsym = submenu->sym;\n\n\t\tswitch (res) {\n\t\tcase ' ':\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_toggle_tristate_value(sym);\n\t\t\telse if (item_is_tag('m'))\n\t\t\t\tconf(submenu);\n\t\t\tbreak;\n\t\tcase KEY_RIGHT:\n\t\tcase 10: /* ENTER WAS PRESSED */\n\t\t\tswitch (item_tag()) {\n\t\t\tcase 'm':\n\t\t\t\tif (single_menu_mode)\n\t\t\t\t\tsubmenu->data =\n\t\t\t\t\t\t(void *) (long) !submenu->data;\n\t\t\t\telse\n\t\t\t\t\tconf(submenu);\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\tif (sym_is_choice(sym) &&\n\t\t\t\t    sym_get_tristate_value(sym) == yes)\n\t\t\t\t\tconf_choice(submenu);\n\t\t\t\telse if (submenu->prompt &&\n\t\t\t\t\t submenu->prompt->type == P_MENU)\n\t\t\t\t\tconf(submenu);\n\t\t\t\telse if (res == 10)\n\t\t\t\t\tsym_toggle_tristate_value(sym);\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tconf_string(submenu);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'y':\n\t\t\tif (item_is_tag('t')) {\n\t\t\t\tif (sym_set_tristate_value(sym, yes))\n\t\t\t\t\tbreak;\n\t\t\t\tif (sym_set_tristate_value(sym, mod))\n\t\t\t\t\tbtn_dialog(main_window, setmod_text, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'n':\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_set_tristate_value(sym, no);\n\t\t\tbreak;\n\t\tcase 'm':\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_set_tristate_value(sym, mod);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic void conf_message_callback(const char *fmt, va_list ap)\n{\n\tchar buf[1024];\n\n\tvsnprintf(buf, sizeof(buf), fmt, ap);\n\tbtn_dialog(main_window, buf, 1, \"<OK>\");\n}\n\nstatic void show_help(struct menu *menu)\n{\n\tstruct gstr help;\n\n\tif (!menu)\n\t\treturn;\n\n\thelp = str_new();\n\tmenu_get_ext_help(menu, &help);\n\tshow_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));\n\tstr_free(&help);\n}\n\nstatic void conf_choice(struct menu *menu)\n{\n\tconst char *prompt = _(menu_get_prompt(menu));\n\tstruct menu *child = 0;\n\tstruct symbol *active;\n\tint selected_index = 0;\n\tint last_top_row = 0;\n\tint res, i = 0;\n\tstruct match_state match_state = {\n\t\t.in_search = 0,\n\t\t.match_direction = MATCH_TINKER_PATTERN_DOWN,\n\t\t.pattern = \"\",\n\t};\n\n\tactive = sym_get_choice_value(menu->sym);\n\t/* this is mostly duplicated from the conf() function. */\n\twhile (!global_exit) {\n\t\treset_menu();\n\n\t\tfor (i = 0, child = menu->list; child; child = child->next) {\n\t\t\tif (!show_all_items && !menu_is_visible(child))\n\t\t\t\tcontinue;\n\n\t\t\tif (child->sym == sym_get_choice_value(menu->sym))\n\t\t\t\titem_make(child, ':', \"<X> %s\",\n\t\t\t\t\t\t_(menu_get_prompt(child)));\n\t\t\telse if (child->sym)\n\t\t\t\titem_make(child, ':', \"    %s\",\n\t\t\t\t\t\t_(menu_get_prompt(child)));\n\t\t\telse\n\t\t\t\titem_make(child, ':', \"*** %s ***\",\n\t\t\t\t\t\t_(menu_get_prompt(child)));\n\n\t\t\tif (child->sym == active){\n\t\t\t\tlast_top_row = top_row(curses_menu);\n\t\t\t\tselected_index = i;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t\tshow_menu(prompt ? _(prompt) : _(\"Choice Menu\"),\n\t\t\t\t_(radiolist_instructions),\n\t\t\t\tselected_index,\n\t\t\t\t&last_top_row);\n\t\twhile (!global_exit) {\n\t\t\tif (match_state.in_search) {\n\t\t\t\tmvprintw(0, 0, \"searching: %s\",\n\t\t\t\t\t match_state.pattern);\n\t\t\t\tclrtoeol();\n\t\t\t}\n\t\t\trefresh_all_windows(main_window);\n\t\t\tres = wgetch(menu_win(curses_menu));\n\t\t\tif (!res)\n\t\t\t\tbreak;\n\t\t\tif (do_match(res, &match_state, &selected_index) == 0) {\n\t\t\t\tif (selected_index != -1)\n\t\t\t\t\tcenter_item(selected_index,\n\t\t\t\t\t\t    &last_top_row);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (process_special_keys(\n\t\t\t\t\t\t&res,\n\t\t\t\t\t\t(struct menu *) item_data()))\n\t\t\t\tbreak;\n\t\t\tswitch (res) {\n\t\t\tcase KEY_DOWN:\n\t\t\t\tmenu_driver(curses_menu, REQ_DOWN_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_UP:\n\t\t\t\tmenu_driver(curses_menu, REQ_UP_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_NPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_DPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_PPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_UPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_HOME:\n\t\t\t\tmenu_driver(curses_menu, REQ_FIRST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_END:\n\t\t\t\tmenu_driver(curses_menu, REQ_LAST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\tcase '?':\n\t\t\t\tshow_help((struct menu *) item_data());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (res == 10 || res == 27 || res == ' ' ||\n\t\t\t\t\tres == KEY_LEFT){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\trefresh_all_windows(main_window);\n\t\t}\n\t\t/* if ESC or left */\n\t\tif (res == 27 || res == KEY_LEFT)\n\t\t\tbreak;\n\n\t\tchild = item_data();\n\t\tif (!child || !menu_is_visible(child) || !child->sym)\n\t\t\tcontinue;\n\t\tswitch (res) {\n\t\tcase ' ':\n\t\tcase  10:\n\t\tcase KEY_RIGHT:\n\t\t\tsym_set_tristate_value(child->sym, yes);\n\t\t\treturn;\n\t\tcase 'h':\n\t\tcase '?':\n\t\t\tshow_help(child);\n\t\t\tactive = child->sym;\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_string(struct menu *menu)\n{\n\tconst char *prompt = menu_get_prompt(menu);\n\n\twhile (1) {\n\t\tint res;\n\t\tconst char *heading;\n\n\t\tswitch (sym_get_type(menu->sym)) {\n\t\tcase S_INT:\n\t\t\theading = _(inputbox_instructions_int);\n\t\t\tbreak;\n\t\tcase S_HEX:\n\t\t\theading = _(inputbox_instructions_hex);\n\t\t\tbreak;\n\t\tcase S_STRING:\n\t\t\theading = _(inputbox_instructions_string);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\theading = _(\"Internal nconf error!\");\n\t\t}\n\t\tres = dialog_inputbox(main_window,\n\t\t\t\tprompt ? _(prompt) : _(\"Main Menu\"),\n\t\t\t\theading,\n\t\t\t\tsym_get_string_value(menu->sym),\n\t\t\t\t&dialog_input_result,\n\t\t\t\t&dialog_input_result_len);\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (sym_set_string_value(menu->sym,\n\t\t\t\t\t\tdialog_input_result))\n\t\t\t\treturn;\n\t\t\tbtn_dialog(main_window,\n\t\t\t\t_(\"You have made an invalid entry.\"), 0);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_help(menu);\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_load(void)\n{\n\twhile (1) {\n\t\tint res;\n\t\tres = dialog_inputbox(main_window,\n\t\t\t\tNULL, load_config_text,\n\t\t\t\tfilename,\n\t\t\t\t&dialog_input_result,\n\t\t\t\t&dialog_input_result_len);\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (!dialog_input_result[0])\n\t\t\t\treturn;\n\t\t\tif (!conf_read(dialog_input_result)) {\n\t\t\t\tset_config_filename(dialog_input_result);\n\t\t\t\tsym_set_change_count(1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbtn_dialog(main_window, _(\"File does not exist!\"), 0);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_scroll_win(main_window,\n\t\t\t\t\t_(\"Load Alternate Configuration\"),\n\t\t\t\t\tload_config_help);\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_save(void)\n{\n\twhile (1) {\n\t\tint res;\n\t\tres = dialog_inputbox(main_window,\n\t\t\t\tNULL, save_config_text,\n\t\t\t\tfilename,\n\t\t\t\t&dialog_input_result,\n\t\t\t\t&dialog_input_result_len);\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (!dialog_input_result[0])\n\t\t\t\treturn;\n\t\t\tres = conf_write(dialog_input_result);\n\t\t\tif (!res) {\n\t\t\t\tset_config_filename(dialog_input_result);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbtn_dialog(main_window, _(\"Can't create file! \"\n\t\t\t\t\"Probably a nonexistent directory.\"),\n\t\t\t\t1, \"<OK>\");\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_scroll_win(main_window,\n\t\t\t\t_(\"Save Alternate Configuration\"),\n\t\t\t\tsave_config_help);\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nvoid setup_windows(void)\n{\n\tint lines, columns;\n\n\tgetmaxyx(stdscr, lines, columns);\n\n\tif (main_window != NULL)\n\t\tdelwin(main_window);\n\n\t/* set up the menu and menu window */\n\tmain_window = newwin(lines-2, columns-2, 2, 1);\n\tkeypad(main_window, TRUE);\n\tmwin_max_lines = lines-7;\n\tmwin_max_cols = columns-6;\n\n\t/* panels order is from bottom to top */\n\tnew_panel(main_window);\n}\n\nint main(int ac, char **av)\n{\n\tint lines, columns;\n\tchar *mode;\n\n\tsetlocale(LC_ALL, \"\");\n\tbindtextdomain(PACKAGE, LOCALEDIR);\n\ttextdomain(PACKAGE);\n\n\tconf_parse(av[1]);\n\tconf_read(NULL);\n\n\tmode = getenv(\"NCONFIG_MODE\");\n\tif (mode) {\n\t\tif (!strcasecmp(mode, \"single_menu\"))\n\t\t\tsingle_menu_mode = 1;\n\t}\n\n\t/* Initialize curses */\n\tinitscr();\n\t/* set color theme */\n\tset_colors();\n\n\tcbreak();\n\tnoecho();\n\tkeypad(stdscr, TRUE);\n\tcurs_set(0);\n\n\tgetmaxyx(stdscr, lines, columns);\n\tif (columns < 75 || lines < 20) {\n\t\tendwin();\n\t\tprintf(\"Your terminal should have at \"\n\t\t\t\"least 20 lines and 75 columns\\n\");\n\t\treturn 1;\n\t}\n\n\tnotimeout(stdscr, FALSE);\n#if NCURSES_REENTRANT\n\tset_escdelay(1);\n#else\n\tESCDELAY = 1;\n#endif\n\n\t/* set btns menu */\n\tcurses_menu = new_menu(curses_menu_items);\n\tmenu_opts_off(curses_menu, O_SHOWDESC);\n\tmenu_opts_on(curses_menu, O_SHOWMATCH);\n\tmenu_opts_on(curses_menu, O_ONEVALUE);\n\tmenu_opts_on(curses_menu, O_NONCYCLIC);\n\tmenu_opts_on(curses_menu, O_IGNORECASE);\n\tset_menu_mark(curses_menu, \" \");\n\tset_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);\n\tset_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);\n\tset_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);\n\n\tset_config_filename(conf_get_configname());\n\tsetup_windows();\n\n\t/* check for KEY_FUNC(1) */\n\tif (has_key(KEY_F(1)) == FALSE) {\n\t\tshow_scroll_win(main_window,\n\t\t\t\t_(\"Instructions\"),\n\t\t\t\t_(menu_no_f_instructions));\n\t}\n\n\tconf_set_message_callback(conf_message_callback);\n\t/* do the work */\n\twhile (!global_exit) {\n\t\tconf(&rootmenu);\n\t\tif (!global_exit && do_exit() == 0)\n\t\t\tbreak;\n\t}\n\t/* ok, we are done */\n\tunpost_menu(curses_menu);\n\tfree_menu(curses_menu);\n\tdelwin(main_window);\n\tclear();\n\trefresh();\n\tendwin();\n\treturn 0;\n}\n\n"
  },
  {
    "path": "kconfig/nconf.gui.c",
    "content": "/*\n * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?\n * Released under the terms of the GNU GPL v2.0.\n *\n * Derived from menuconfig.\n *\n */\n#include \"nconf.h\"\n\n/* a list of all the different widgets we use */\nattributes_t attributes[ATTR_MAX+1] = {0};\n\n/* available colors:\n   COLOR_BLACK   0\n   COLOR_RED     1\n   COLOR_GREEN   2\n   COLOR_YELLOW  3\n   COLOR_BLUE    4\n   COLOR_MAGENTA 5\n   COLOR_CYAN    6\n   COLOR_WHITE   7\n   */\nstatic void set_normal_colors(void)\n{\n\tinit_pair(NORMAL, -1, -1);\n\tinit_pair(MAIN_HEADING, COLOR_MAGENTA, -1);\n\n\t/* FORE is for the selected item */\n\tinit_pair(MAIN_MENU_FORE, -1, -1);\n\t/* BACK for all the rest */\n\tinit_pair(MAIN_MENU_BACK, -1, -1);\n\tinit_pair(MAIN_MENU_GREY, -1, -1);\n\tinit_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);\n\tinit_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);\n\n\tinit_pair(SCROLLWIN_TEXT, -1, -1);\n\tinit_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);\n\tinit_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);\n\n\tinit_pair(DIALOG_TEXT, -1, -1);\n\tinit_pair(DIALOG_BOX, COLOR_YELLOW, -1);\n\tinit_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);\n\tinit_pair(DIALOG_MENU_FORE, COLOR_RED, -1);\n\n\tinit_pair(INPUT_BOX, COLOR_YELLOW, -1);\n\tinit_pair(INPUT_HEADING, COLOR_GREEN, -1);\n\tinit_pair(INPUT_TEXT, -1, -1);\n\tinit_pair(INPUT_FIELD, -1, -1);\n\n\tinit_pair(FUNCTION_HIGHLIGHT, -1, -1);\n\tinit_pair(FUNCTION_TEXT, COLOR_YELLOW, -1);\n}\n\n/* available attributes:\n   A_NORMAL        Normal display (no highlight)\n   A_STANDOUT      Best highlighting mode of the terminal.\n   A_UNDERLINE     Underlining\n   A_REVERSE       Reverse video\n   A_BLINK         Blinking\n   A_DIM           Half bright\n   A_BOLD          Extra bright or bold\n   A_PROTECT       Protected mode\n   A_INVIS         Invisible or blank mode\n   A_ALTCHARSET    Alternate character set\n   A_CHARTEXT      Bit-mask to extract a character\n   COLOR_PAIR(n)   Color-pair number n\n   */\nstatic void normal_color_theme(void)\n{\n\t/* automatically add color... */\n#define mkattr(name, attr) do { \\\nattributes[name] = attr | COLOR_PAIR(name); } while (0)\n\tmkattr(NORMAL, NORMAL);\n\tmkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);\n\n\tmkattr(MAIN_MENU_FORE, A_REVERSE);\n\tmkattr(MAIN_MENU_BACK, A_NORMAL);\n\tmkattr(MAIN_MENU_GREY, A_NORMAL);\n\tmkattr(MAIN_MENU_HEADING, A_BOLD);\n\tmkattr(MAIN_MENU_BOX, A_NORMAL);\n\n\tmkattr(SCROLLWIN_TEXT, A_NORMAL);\n\tmkattr(SCROLLWIN_HEADING, A_BOLD);\n\tmkattr(SCROLLWIN_BOX, A_BOLD);\n\n\tmkattr(DIALOG_TEXT, A_BOLD);\n\tmkattr(DIALOG_BOX, A_BOLD);\n\tmkattr(DIALOG_MENU_FORE, A_STANDOUT);\n\tmkattr(DIALOG_MENU_BACK, A_NORMAL);\n\n\tmkattr(INPUT_BOX, A_NORMAL);\n\tmkattr(INPUT_HEADING, A_BOLD);\n\tmkattr(INPUT_TEXT, A_NORMAL);\n\tmkattr(INPUT_FIELD, A_UNDERLINE);\n\n\tmkattr(FUNCTION_HIGHLIGHT, A_BOLD);\n\tmkattr(FUNCTION_TEXT, A_REVERSE);\n}\n\nstatic void no_colors_theme(void)\n{\n\t/* automatically add highlight, no color */\n#define mkattrn(name, attr) { attributes[name] = attr; }\n\n\tmkattrn(NORMAL, NORMAL);\n\tmkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);\n\n\tmkattrn(MAIN_MENU_FORE, A_STANDOUT);\n\tmkattrn(MAIN_MENU_BACK, A_NORMAL);\n\tmkattrn(MAIN_MENU_GREY, A_NORMAL);\n\tmkattrn(MAIN_MENU_HEADING, A_BOLD);\n\tmkattrn(MAIN_MENU_BOX, A_NORMAL);\n\n\tmkattrn(SCROLLWIN_TEXT, A_NORMAL);\n\tmkattrn(SCROLLWIN_HEADING, A_BOLD);\n\tmkattrn(SCROLLWIN_BOX, A_BOLD);\n\n\tmkattrn(DIALOG_TEXT, A_NORMAL);\n\tmkattrn(DIALOG_BOX, A_BOLD);\n\tmkattrn(DIALOG_MENU_FORE, A_STANDOUT);\n\tmkattrn(DIALOG_MENU_BACK, A_NORMAL);\n\n\tmkattrn(INPUT_BOX, A_BOLD);\n\tmkattrn(INPUT_HEADING, A_BOLD);\n\tmkattrn(INPUT_TEXT, A_NORMAL);\n\tmkattrn(INPUT_FIELD, A_UNDERLINE);\n\n\tmkattrn(FUNCTION_HIGHLIGHT, A_BOLD);\n\tmkattrn(FUNCTION_TEXT, A_REVERSE);\n}\n\nvoid set_colors()\n{\n\tstart_color();\n\tuse_default_colors();\n\tset_normal_colors();\n\tif (has_colors()) {\n\t\tnormal_color_theme();\n\t} else {\n\t\t/* give defaults */\n\t\tno_colors_theme();\n\t}\n}\n\n\n/* this changes the windows attributes !!! */\nvoid print_in_middle(WINDOW *win,\n\t\tint starty,\n\t\tint startx,\n\t\tint width,\n\t\tconst char *string,\n\t\tchtype color)\n{      int length, x, y;\n\tfloat temp;\n\n\n\tif (win == NULL)\n\t\twin = stdscr;\n\tgetyx(win, y, x);\n\tif (startx != 0)\n\t\tx = startx;\n\tif (starty != 0)\n\t\ty = starty;\n\tif (width == 0)\n\t\twidth = 80;\n\n\tlength = strlen(string);\n\ttemp = (width - length) / 2;\n\tx = startx + (int)temp;\n\t(void) wattrset(win, color);\n\tmvwprintw(win, y, x, \"%s\", string);\n\trefresh();\n}\n\nint get_line_no(const char *text)\n{\n\tint i;\n\tint total = 1;\n\n\tif (!text)\n\t\treturn 0;\n\n\tfor (i = 0; text[i] != '\\0'; i++)\n\t\tif (text[i] == '\\n')\n\t\t\ttotal++;\n\treturn total;\n}\n\nconst char *get_line(const char *text, int line_no)\n{\n\tint i;\n\tint lines = 0;\n\n\tif (!text)\n\t\treturn 0;\n\n\tfor (i = 0; text[i] != '\\0' && lines < line_no; i++)\n\t\tif (text[i] == '\\n')\n\t\t\tlines++;\n\treturn text+i;\n}\n\nint get_line_length(const char *line)\n{\n\tint res = 0;\n\twhile (*line != '\\0' && *line != '\\n') {\n\t\tline++;\n\t\tres++;\n\t}\n\treturn res;\n}\n\n/* print all lines to the window. */\nvoid fill_window(WINDOW *win, const char *text)\n{\n\tint x, y;\n\tint total_lines = get_line_no(text);\n\tint i;\n\n\tgetmaxyx(win, y, x);\n\t/* do not go over end of line */\n\ttotal_lines = min(total_lines, y);\n\tfor (i = 0; i < total_lines; i++) {\n\t\tchar tmp[x+10];\n\t\tconst char *line = get_line(text, i);\n\t\tint len = get_line_length(line);\n\t\tstrncpy(tmp, line, min(len, x));\n\t\ttmp[len] = '\\0';\n\t\tmvwprintw(win, i, 0, \"%s\", tmp);\n\t}\n}\n\n/* get the message, and buttons.\n * each button must be a char*\n * return the selected button\n *\n * this dialog is used for 2 different things:\n * 1) show a text box, no buttons.\n * 2) show a dialog, with horizontal buttons\n */\nint btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)\n{\n\tva_list ap;\n\tchar *btn;\n\tint btns_width = 0;\n\tint msg_lines = 0;\n\tint msg_width = 0;\n\tint total_width;\n\tint win_rows = 0;\n\tWINDOW *win;\n\tWINDOW *msg_win;\n\tWINDOW *menu_win;\n\tMENU *menu;\n\tITEM *btns[btn_num+1];\n\tint i, x, y;\n\tint res = -1;\n\n\n\tva_start(ap, btn_num);\n\tfor (i = 0; i < btn_num; i++) {\n\t\tbtn = va_arg(ap, char *);\n\t\tbtns[i] = new_item(btn, \"\");\n\t\tbtns_width += strlen(btn)+1;\n\t}\n\tva_end(ap);\n\tbtns[btn_num] = NULL;\n\n\t/* find the widest line of msg: */\n\tmsg_lines = get_line_no(msg);\n\tfor (i = 0; i < msg_lines; i++) {\n\t\tconst char *line = get_line(msg, i);\n\t\tint len = get_line_length(line);\n\t\tif (msg_width < len)\n\t\t\tmsg_width = len;\n\t}\n\n\ttotal_width = max(msg_width, btns_width);\n\t/* place dialog in middle of screen */\n\ty = (getmaxy(stdscr)-(msg_lines+4))/2;\n\tx = (getmaxx(stdscr)-(total_width+4))/2;\n\n\n\t/* create the windows */\n\tif (btn_num > 0)\n\t\twin_rows = msg_lines+4;\n\telse\n\t\twin_rows = msg_lines+2;\n\n\twin = newwin(win_rows, total_width+4, y, x);\n\tkeypad(win, TRUE);\n\tmenu_win = derwin(win, 1, btns_width, win_rows-2,\n\t\t\t1+(total_width+2-btns_width)/2);\n\tmenu = new_menu(btns);\n\tmsg_win = derwin(win, win_rows-2, msg_width, 1,\n\t\t\t1+(total_width+2-msg_width)/2);\n\n\tset_menu_fore(menu, attributes[DIALOG_MENU_FORE]);\n\tset_menu_back(menu, attributes[DIALOG_MENU_BACK]);\n\n\t(void) wattrset(win, attributes[DIALOG_BOX]);\n\tbox(win, 0, 0);\n\n\t/* print message */\n\t(void) wattrset(msg_win, attributes[DIALOG_TEXT]);\n\tfill_window(msg_win, msg);\n\n\tset_menu_win(menu, win);\n\tset_menu_sub(menu, menu_win);\n\tset_menu_format(menu, 1, btn_num);\n\tmenu_opts_off(menu, O_SHOWDESC);\n\tmenu_opts_off(menu, O_SHOWMATCH);\n\tmenu_opts_on(menu, O_ONEVALUE);\n\tmenu_opts_on(menu, O_NONCYCLIC);\n\tset_menu_mark(menu, \"\");\n\tpost_menu(menu);\n\n\n\ttouchwin(win);\n\trefresh_all_windows(main_window);\n\twhile ((res = wgetch(win))) {\n\t\tswitch (res) {\n\t\tcase KEY_LEFT:\n\t\t\tmenu_driver(menu, REQ_LEFT_ITEM);\n\t\t\tbreak;\n\t\tcase KEY_RIGHT:\n\t\t\tmenu_driver(menu, REQ_RIGHT_ITEM);\n\t\t\tbreak;\n\t\tcase 10: /* ENTER */\n\t\tcase 27: /* ESCAPE */\n\t\tcase ' ':\n\t\tcase KEY_F(F_BACK):\n\t\tcase KEY_F(F_EXIT):\n\t\t\tbreak;\n\t\t}\n\t\ttouchwin(win);\n\t\trefresh_all_windows(main_window);\n\n\t\tif (res == 10 || res == ' ') {\n\t\t\tres = item_index(current_item(menu));\n\t\t\tbreak;\n\t\t} else if (res == 27 || res == KEY_F(F_BACK) ||\n\t\t\t\tres == KEY_F(F_EXIT)) {\n\t\t\tres = KEY_EXIT;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tunpost_menu(menu);\n\tfree_menu(menu);\n\tfor (i = 0; i < btn_num; i++)\n\t\tfree_item(btns[i]);\n\n\tdelwin(win);\n\treturn res;\n}\n\nint dialog_inputbox(WINDOW *main_window,\n\t\tconst char *title, const char *prompt,\n\t\tconst char *init, char **resultp, int *result_len)\n{\n\tint prompt_lines = 0;\n\tint prompt_width = 0;\n\tWINDOW *win;\n\tWINDOW *prompt_win;\n\tWINDOW *form_win;\n\tPANEL *panel;\n\tint i, x, y;\n\tint res = -1;\n\tint cursor_position = strlen(init);\n\tint cursor_form_win;\n\tchar *result = *resultp;\n\n\tif (strlen(init)+1 > *result_len) {\n\t\t*result_len = strlen(init)+1;\n\t\t*resultp = result = realloc(result, *result_len);\n\t}\n\n\t/* find the widest line of msg: */\n\tprompt_lines = get_line_no(prompt);\n\tfor (i = 0; i < prompt_lines; i++) {\n\t\tconst char *line = get_line(prompt, i);\n\t\tint len = get_line_length(line);\n\t\tprompt_width = max(prompt_width, len);\n\t}\n\n\tif (title)\n\t\tprompt_width = max(prompt_width, strlen(title));\n\n\t/* place dialog in middle of screen */\n\ty = (getmaxy(stdscr)-(prompt_lines+4))/2;\n\tx = (getmaxx(stdscr)-(prompt_width+4))/2;\n\n\tstrncpy(result, init, *result_len);\n\n\t/* create the windows */\n\twin = newwin(prompt_lines+6, prompt_width+7, y, x);\n\tprompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);\n\tform_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);\n\tkeypad(form_win, TRUE);\n\n\t(void) wattrset(form_win, attributes[INPUT_FIELD]);\n\n\t(void) wattrset(win, attributes[INPUT_BOX]);\n\tbox(win, 0, 0);\n\t(void) wattrset(win, attributes[INPUT_HEADING]);\n\tif (title)\n\t\tmvwprintw(win, 0, 3, \"%s\", title);\n\n\t/* print message */\n\t(void) wattrset(prompt_win, attributes[INPUT_TEXT]);\n\tfill_window(prompt_win, prompt);\n\n\tmvwprintw(form_win, 0, 0, \"%*s\", prompt_width, \" \");\n\tcursor_form_win = min(cursor_position, prompt_width-1);\n\tmvwprintw(form_win, 0, 0, \"%s\",\n\t\t  result + cursor_position-cursor_form_win);\n\n\t/* create panels */\n\tpanel = new_panel(win);\n\n\t/* show the cursor */\n\tcurs_set(1);\n\n\ttouchwin(win);\n\trefresh_all_windows(main_window);\n\twhile ((res = wgetch(form_win))) {\n\t\tint len = strlen(result);\n\t\tswitch (res) {\n\t\tcase 10: /* ENTER */\n\t\tcase 27: /* ESCAPE */\n\t\tcase KEY_F(F_HELP):\n\t\tcase KEY_F(F_EXIT):\n\t\tcase KEY_F(F_BACK):\n\t\t\tbreak;\n\t\tcase 127:\n\t\tcase KEY_BACKSPACE:\n\t\t\tif (cursor_position > 0) {\n\t\t\t\tmemmove(&result[cursor_position-1],\n\t\t\t\t\t\t&result[cursor_position],\n\t\t\t\t\t\tlen-cursor_position+1);\n\t\t\t\tcursor_position--;\n\t\t\t\tcursor_form_win--;\n\t\t\t\tlen--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_DC:\n\t\t\tif (cursor_position >= 0 && cursor_position < len) {\n\t\t\t\tmemmove(&result[cursor_position],\n\t\t\t\t\t\t&result[cursor_position+1],\n\t\t\t\t\t\tlen-cursor_position+1);\n\t\t\t\tlen--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_UP:\n\t\tcase KEY_RIGHT:\n\t\t\tif (cursor_position < len) {\n\t\t\t\tcursor_position++;\n\t\t\t\tcursor_form_win++;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_DOWN:\n\t\tcase KEY_LEFT:\n\t\t\tif (cursor_position > 0) {\n\t\t\t\tcursor_position--;\n\t\t\t\tcursor_form_win--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_HOME:\n\t\t\tcursor_position = 0;\n\t\t\tcursor_form_win = 0;\n\t\t\tbreak;\n\t\tcase KEY_END:\n\t\t\tcursor_position = len;\n\t\t\tcursor_form_win = min(cursor_position, prompt_width-1);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif ((isgraph(res) || isspace(res))) {\n\t\t\t\t/* one for new char, one for '\\0' */\n\t\t\t\tif (len+2 > *result_len) {\n\t\t\t\t\t*result_len = len+2;\n\t\t\t\t\t*resultp = result = realloc(result,\n\t\t\t\t\t\t\t\t*result_len);\n\t\t\t\t}\n\t\t\t\t/* insert the char at the proper position */\n\t\t\t\tmemmove(&result[cursor_position+1],\n\t\t\t\t\t\t&result[cursor_position],\n\t\t\t\t\t\tlen-cursor_position+1);\n\t\t\t\tresult[cursor_position] = res;\n\t\t\t\tcursor_position++;\n\t\t\t\tcursor_form_win++;\n\t\t\t\tlen++;\n\t\t\t} else {\n\t\t\t\tmvprintw(0, 0, \"unknown key: %d\\n\", res);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (cursor_form_win < 0)\n\t\t\tcursor_form_win = 0;\n\t\telse if (cursor_form_win > prompt_width-1)\n\t\t\tcursor_form_win = prompt_width-1;\n\n\t\twmove(form_win, 0, 0);\n\t\twclrtoeol(form_win);\n\t\tmvwprintw(form_win, 0, 0, \"%*s\", prompt_width, \" \");\n\t\tmvwprintw(form_win, 0, 0, \"%s\",\n\t\t\tresult + cursor_position-cursor_form_win);\n\t\twmove(form_win, 0, cursor_form_win);\n\t\ttouchwin(win);\n\t\trefresh_all_windows(main_window);\n\n\t\tif (res == 10) {\n\t\t\tres = 0;\n\t\t\tbreak;\n\t\t} else if (res == 27 || res == KEY_F(F_BACK) ||\n\t\t\t\tres == KEY_F(F_EXIT)) {\n\t\t\tres = KEY_EXIT;\n\t\t\tbreak;\n\t\t} else if (res == KEY_F(F_HELP)) {\n\t\t\tres = 1;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* hide the cursor */\n\tcurs_set(0);\n\tdel_panel(panel);\n\tdelwin(prompt_win);\n\tdelwin(form_win);\n\tdelwin(win);\n\treturn res;\n}\n\n/* refresh all windows in the correct order */\nvoid refresh_all_windows(WINDOW *main_window)\n{\n\tupdate_panels();\n\ttouchwin(main_window);\n\trefresh();\n}\n\n/* layman's scrollable window... */\nvoid show_scroll_win(WINDOW *main_window,\n\t\tconst char *title,\n\t\tconst char *text)\n{\n\tint res;\n\tint total_lines = get_line_no(text);\n\tint x, y, lines, columns;\n\tint start_x = 0, start_y = 0;\n\tint text_lines = 0, text_cols = 0;\n\tint total_cols = 0;\n\tint win_cols = 0;\n\tint win_lines = 0;\n\tint i = 0;\n\tWINDOW *win;\n\tWINDOW *pad;\n\tPANEL *panel;\n\n\tgetmaxyx(stdscr, lines, columns);\n\n\t/* find the widest line of msg: */\n\ttotal_lines = get_line_no(text);\n\tfor (i = 0; i < total_lines; i++) {\n\t\tconst char *line = get_line(text, i);\n\t\tint len = get_line_length(line);\n\t\ttotal_cols = max(total_cols, len+2);\n\t}\n\n\t/* create the pad */\n\tpad = newpad(total_lines+10, total_cols+10);\n\t(void) wattrset(pad, attributes[SCROLLWIN_TEXT]);\n\tfill_window(pad, text);\n\n\twin_lines = min(total_lines+4, lines-2);\n\twin_cols = min(total_cols+2, columns-2);\n\ttext_lines = max(win_lines-4, 0);\n\ttext_cols = max(win_cols-2, 0);\n\n\t/* place window in middle of screen */\n\ty = (lines-win_lines)/2;\n\tx = (columns-win_cols)/2;\n\n\twin = newwin(win_lines, win_cols, y, x);\n\tkeypad(win, TRUE);\n\t/* show the help in the help window, and show the help panel */\n\t(void) wattrset(win, attributes[SCROLLWIN_BOX]);\n\tbox(win, 0, 0);\n\t(void) wattrset(win, attributes[SCROLLWIN_HEADING]);\n\tmvwprintw(win, 0, 3, \" %s \", title);\n\tpanel = new_panel(win);\n\n\t/* handle scrolling */\n\tdo {\n\n\t\tcopywin(pad, win, start_y, start_x, 2, 2, text_lines,\n\t\t\t\ttext_cols, 0);\n\t\tprint_in_middle(win,\n\t\t\t\ttext_lines+2,\n\t\t\t\t0,\n\t\t\t\ttext_cols,\n\t\t\t\t\"<OK>\",\n\t\t\t\tattributes[DIALOG_MENU_FORE]);\n\t\twrefresh(win);\n\n\t\tres = wgetch(win);\n\t\tswitch (res) {\n\t\tcase KEY_NPAGE:\n\t\tcase ' ':\n\t\tcase 'd':\n\t\t\tstart_y += text_lines-2;\n\t\t\tbreak;\n\t\tcase KEY_PPAGE:\n\t\tcase 'u':\n\t\t\tstart_y -= text_lines+2;\n\t\t\tbreak;\n\t\tcase KEY_HOME:\n\t\t\tstart_y = 0;\n\t\t\tbreak;\n\t\tcase KEY_END:\n\t\t\tstart_y = total_lines-text_lines;\n\t\t\tbreak;\n\t\tcase KEY_DOWN:\n\t\tcase 'j':\n\t\t\tstart_y++;\n\t\t\tbreak;\n\t\tcase KEY_UP:\n\t\tcase 'k':\n\t\t\tstart_y--;\n\t\t\tbreak;\n\t\tcase KEY_LEFT:\n\t\tcase 'h':\n\t\t\tstart_x--;\n\t\t\tbreak;\n\t\tcase KEY_RIGHT:\n\t\tcase 'l':\n\t\t\tstart_x++;\n\t\t\tbreak;\n\t\t}\n\t\tif (res == 10 || res == 27 || res == 'q' ||\n\t\t\tres == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||\n\t\t\tres == KEY_F(F_EXIT))\n\t\t\tbreak;\n\t\tif (start_y < 0)\n\t\t\tstart_y = 0;\n\t\tif (start_y >= total_lines-text_lines)\n\t\t\tstart_y = total_lines-text_lines;\n\t\tif (start_x < 0)\n\t\t\tstart_x = 0;\n\t\tif (start_x >= total_cols-text_cols)\n\t\t\tstart_x = total_cols-text_cols;\n\t} while (res);\n\n\tdel_panel(panel);\n\tdelwin(win);\n\trefresh_all_windows(main_window);\n}\n"
  },
  {
    "path": "kconfig/nconf.h",
    "content": "/*\n * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?\n * Released under the terms of the GNU GPL v2.0.\n *\n * Derived from menuconfig.\n *\n */\n\n#include <ctype.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <locale.h>\n#include <curses.h>\n#include <menu.h>\n#include <panel.h>\n#include <form.h>\n\n#include <stdio.h>\n#include <time.h>\n#include <sys/time.h>\n\n#include \"ncurses.h\"\n\n#define max(a, b) ({\\\n\t\ttypeof(a) _a = a;\\\n\t\ttypeof(b) _b = b;\\\n\t\t_a > _b ? _a : _b; })\n\n#define min(a, b) ({\\\n\t\ttypeof(a) _a = a;\\\n\t\ttypeof(b) _b = b;\\\n\t\t_a < _b ? _a : _b; })\n\ntypedef enum {\n\tNORMAL = 1,\n\tMAIN_HEADING,\n\tMAIN_MENU_BOX,\n\tMAIN_MENU_FORE,\n\tMAIN_MENU_BACK,\n\tMAIN_MENU_GREY,\n\tMAIN_MENU_HEADING,\n\tSCROLLWIN_TEXT,\n\tSCROLLWIN_HEADING,\n\tSCROLLWIN_BOX,\n\tDIALOG_TEXT,\n\tDIALOG_MENU_FORE,\n\tDIALOG_MENU_BACK,\n\tDIALOG_BOX,\n\tINPUT_BOX,\n\tINPUT_HEADING,\n\tINPUT_TEXT,\n\tINPUT_FIELD,\n\tFUNCTION_TEXT,\n\tFUNCTION_HIGHLIGHT,\n\tATTR_MAX\n} attributes_t;\nextern attributes_t attributes[];\n\ntypedef enum {\n\tF_HELP = 1,\n\tF_SYMBOL = 2,\n\tF_INSTS = 3,\n\tF_CONF = 4,\n\tF_BACK = 5,\n\tF_SAVE = 6,\n\tF_LOAD = 7,\n\tF_SEARCH = 8,\n\tF_EXIT = 9,\n} function_key;\n\nvoid set_colors(void);\n\n/* this changes the windows attributes !!! */\nvoid print_in_middle(WINDOW *win,\n\t\tint starty,\n\t\tint startx,\n\t\tint width,\n\t\tconst char *string,\n\t\tchtype color);\nint get_line_length(const char *line);\nint get_line_no(const char *text);\nconst char *get_line(const char *text, int line_no);\nvoid fill_window(WINDOW *win, const char *text);\nint btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);\nint dialog_inputbox(WINDOW *main_window,\n\t\tconst char *title, const char *prompt,\n\t\tconst char *init, char **resultp, int *result_len);\nvoid refresh_all_windows(WINDOW *main_window);\nvoid show_scroll_win(WINDOW *main_window,\n\t\tconst char *title,\n\t\tconst char *text);\n"
  },
  {
    "path": "kconfig/qconf.cc",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <qglobal.h>\n\n#if QT_VERSION < 0x040000\n#include <stddef.h>\n#include <qmainwindow.h>\n#include <qvbox.h>\n#include <qvaluelist.h>\n#include <qtextbrowser.h>\n#include <qaction.h>\n#include <qheader.h>\n#include <qfiledialog.h>\n#include <qdragobject.h>\n#include <qpopupmenu.h>\n#else\n#include <q3mainwindow.h>\n#include <q3vbox.h>\n#include <q3valuelist.h>\n#include <q3textbrowser.h>\n#include <q3action.h>\n#include <q3header.h>\n#include <q3filedialog.h>\n#include <q3dragobject.h>\n#include <q3popupmenu.h>\n#endif\n\n#include <qapplication.h>\n#include <qdesktopwidget.h>\n#include <qtoolbar.h>\n#include <qlayout.h>\n#include <qsplitter.h>\n#include <qlineedit.h>\n#include <qlabel.h>\n#include <qpushbutton.h>\n#include <qmenubar.h>\n#include <qmessagebox.h>\n#include <qregexp.h>\n#include <qevent.h>\n\n#include <stdlib.h>\n\n#include \"lkc.h\"\n#include \"qconf.h\"\n\n#include \"qconf.moc\"\n#include \"images.c\"\n\n#ifdef _\n# undef _\n# define _ qgettext\n#endif\n\nstatic QApplication *configApp;\nstatic ConfigSettings *configSettings;\n\nQ3Action *ConfigMainWindow::saveAction;\n\nstatic inline QString qgettext(const char* str)\n{\n\treturn QString::fromLocal8Bit(gettext(str));\n}\n\nstatic inline QString qgettext(const QString& str)\n{\n\treturn QString::fromLocal8Bit(gettext(str.latin1()));\n}\n\nConfigSettings::ConfigSettings()\n\t: QSettings(\"kernel.org\", \"qconf\")\n{\n}\n\n/**\n * Reads a list of integer values from the application settings.\n */\nQ3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)\n{\n\tQ3ValueList<int> result;\n\tQStringList entryList = readListEntry(key, ok);\n\tQStringList::Iterator it;\n\n\tfor (it = entryList.begin(); it != entryList.end(); ++it)\n\t\tresult.push_back((*it).toInt());\n\n\treturn result;\n}\n\n/**\n * Writes a list of integer values to the application settings.\n */\nbool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)\n{\n\tQStringList stringList;\n\tQ3ValueList<int>::ConstIterator it;\n\n\tfor (it = value.begin(); it != value.end(); ++it)\n\t\tstringList.push_back(QString::number(*it));\n\treturn writeEntry(key, stringList);\n}\n\n\n/*\n * set the new data\n * TODO check the value\n */\nvoid ConfigItem::okRename(int col)\n{\n\tParent::okRename(col);\n\tsym_set_string_value(menu->sym, text(dataColIdx).latin1());\n\tlistView()->updateList(this);\n}\n\n/*\n * update the displayed of a menu entry\n */\nvoid ConfigItem::updateMenu(void)\n{\n\tConfigList* list;\n\tstruct symbol* sym;\n\tstruct property *prop;\n\tQString prompt;\n\tint type;\n\ttristate expr;\n\n\tlist = listView();\n\tif (goParent) {\n\t\tsetPixmap(promptColIdx, list->menuBackPix);\n\t\tprompt = \"..\";\n\t\tgoto set_prompt;\n\t}\n\n\tsym = menu->sym;\n\tprop = menu->prompt;\n\tprompt = _(menu_get_prompt(menu));\n\n\tif (prop) switch (prop->type) {\n\tcase P_MENU:\n\t\tif (list->mode == singleMode || list->mode == symbolMode) {\n\t\t\t/* a menuconfig entry is displayed differently\n\t\t\t * depending whether it's at the view root or a child.\n\t\t\t */\n\t\t\tif (sym && list->rootEntry == menu)\n\t\t\t\tbreak;\n\t\t\tsetPixmap(promptColIdx, list->menuPix);\n\t\t} else {\n\t\t\tif (sym)\n\t\t\t\tbreak;\n\t\t\tsetPixmap(promptColIdx, 0);\n\t\t}\n\t\tgoto set_prompt;\n\tcase P_COMMENT:\n\t\tsetPixmap(promptColIdx, 0);\n\t\tgoto set_prompt;\n\tdefault:\n\t\t;\n\t}\n\tif (!sym)\n\t\tgoto set_prompt;\n\n\tsetText(nameColIdx, QString::fromLocal8Bit(sym->name));\n\n\ttype = sym_get_type(sym);\n\tswitch (type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tchar ch;\n\n\t\tif (!sym_is_changable(sym) && list->optMode == normalOpt) {\n\t\t\tsetPixmap(promptColIdx, 0);\n\t\t\tsetText(noColIdx, QString::null);\n\t\t\tsetText(modColIdx, QString::null);\n\t\t\tsetText(yesColIdx, QString::null);\n\t\t\tbreak;\n\t\t}\n\t\texpr = sym_get_tristate_value(sym);\n\t\tswitch (expr) {\n\t\tcase yes:\n\t\t\tif (sym_is_choice_value(sym) && type == S_BOOLEAN)\n\t\t\t\tsetPixmap(promptColIdx, list->choiceYesPix);\n\t\t\telse\n\t\t\t\tsetPixmap(promptColIdx, list->symbolYesPix);\n\t\t\tsetText(yesColIdx, \"Y\");\n\t\t\tch = 'Y';\n\t\t\tbreak;\n\t\tcase mod:\n\t\t\tsetPixmap(promptColIdx, list->symbolModPix);\n\t\t\tsetText(modColIdx, \"M\");\n\t\t\tch = 'M';\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (sym_is_choice_value(sym) && type == S_BOOLEAN)\n\t\t\t\tsetPixmap(promptColIdx, list->choiceNoPix);\n\t\t\telse\n\t\t\t\tsetPixmap(promptColIdx, list->symbolNoPix);\n\t\t\tsetText(noColIdx, \"N\");\n\t\t\tch = 'N';\n\t\t\tbreak;\n\t\t}\n\t\tif (expr != no)\n\t\t\tsetText(noColIdx, sym_tristate_within_range(sym, no) ? \"_\" : 0);\n\t\tif (expr != mod)\n\t\t\tsetText(modColIdx, sym_tristate_within_range(sym, mod) ? \"_\" : 0);\n\t\tif (expr != yes)\n\t\t\tsetText(yesColIdx, sym_tristate_within_range(sym, yes) ? \"_\" : 0);\n\n\t\tsetText(dataColIdx, QChar(ch));\n\t\tbreak;\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tconst char* data;\n\n\t\tdata = sym_get_string_value(sym);\n\n\t\tint i = list->mapIdx(dataColIdx);\n\t\tif (i >= 0)\n\t\t\tsetRenameEnabled(i, TRUE);\n\t\tsetText(dataColIdx, data);\n\t\tif (type == S_STRING)\n\t\t\tprompt = QString(\"%1: %2\").arg(prompt).arg(data);\n\t\telse\n\t\t\tprompt = QString(\"(%2) %1\").arg(prompt).arg(data);\n\t\tbreak;\n\t}\n\tif (!sym_has_value(sym) && visible)\n\t\tprompt += _(\" (NEW)\");\nset_prompt:\n\tsetText(promptColIdx, prompt);\n}\n\nvoid ConfigItem::testUpdateMenu(bool v)\n{\n\tConfigItem* i;\n\n\tvisible = v;\n\tif (!menu)\n\t\treturn;\n\n\tsym_calc_value(menu->sym);\n\tif (menu->flags & MENU_CHANGED) {\n\t\t/* the menu entry changed, so update all list items */\n\t\tmenu->flags &= ~MENU_CHANGED;\n\t\tfor (i = (ConfigItem*)menu->data; i; i = i->nextItem)\n\t\t\ti->updateMenu();\n\t} else if (listView()->updateAll)\n\t\tupdateMenu();\n}\n\nvoid ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)\n{\n\tConfigList* list = listView();\n\n\tif (visible) {\n\t\tif (isSelected() && !list->hasFocus() && list->mode == menuMode)\n\t\t\tParent::paintCell(p, list->inactivedColorGroup, column, width, align);\n\t\telse\n\t\t\tParent::paintCell(p, cg, column, width, align);\n\t} else\n\t\tParent::paintCell(p, list->disabledColorGroup, column, width, align);\n}\n\n/*\n * construct a menu entry\n */\nvoid ConfigItem::init(void)\n{\n\tif (menu) {\n\t\tConfigList* list = listView();\n\t\tnextItem = (ConfigItem*)menu->data;\n\t\tmenu->data = this;\n\n\t\tif (list->mode != fullMode)\n\t\t\tsetOpen(TRUE);\n\t\tsym_calc_value(menu->sym);\n\t}\n\tupdateMenu();\n}\n\n/*\n * destruct a menu entry\n */\nConfigItem::~ConfigItem(void)\n{\n\tif (menu) {\n\t\tConfigItem** ip = (ConfigItem**)&menu->data;\n\t\tfor (; *ip; ip = &(*ip)->nextItem) {\n\t\t\tif (*ip == this) {\n\t\t\t\t*ip = nextItem;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nConfigLineEdit::ConfigLineEdit(ConfigView* parent)\n\t: Parent(parent)\n{\n\tconnect(this, SIGNAL(lostFocus()), SLOT(hide()));\n}\n\nvoid ConfigLineEdit::show(ConfigItem* i)\n{\n\titem = i;\n\tif (sym_get_string_value(item->menu->sym))\n\t\tsetText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));\n\telse\n\t\tsetText(QString::null);\n\tParent::show();\n\tsetFocus();\n}\n\nvoid ConfigLineEdit::keyPressEvent(QKeyEvent* e)\n{\n\tswitch (e->key()) {\n\tcase Qt::Key_Escape:\n\t\tbreak;\n\tcase Qt::Key_Return:\n\tcase Qt::Key_Enter:\n\t\tsym_set_string_value(item->menu->sym, text().latin1());\n\t\tparent()->updateList(item);\n\t\tbreak;\n\tdefault:\n\t\tParent::keyPressEvent(e);\n\t\treturn;\n\t}\n\te->accept();\n\tparent()->list->setFocus();\n\thide();\n}\n\nConfigList::ConfigList(ConfigView* p, const char *name)\n\t: Parent(p, name),\n\t  updateAll(false),\n\t  symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),\n\t  choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),\n\t  menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),\n\t  showName(false), showRange(false), showData(false), optMode(normalOpt),\n\t  rootEntry(0), headerPopup(0)\n{\n\tint i;\n\n\tsetSorting(-1);\n\tsetRootIsDecorated(TRUE);\n\tdisabledColorGroup = palette().active();\n\tdisabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());\n\tinactivedColorGroup = palette().active();\n\tinactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());\n\n\tconnect(this, SIGNAL(selectionChanged(void)),\n\t\tSLOT(updateSelection(void)));\n\n\tif (name) {\n\t\tconfigSettings->beginGroup(name);\n\t\tshowName = configSettings->readBoolEntry(\"/showName\", false);\n\t\tshowRange = configSettings->readBoolEntry(\"/showRange\", false);\n\t\tshowData = configSettings->readBoolEntry(\"/showData\", false);\n\t\toptMode = (enum optionMode)configSettings->readNumEntry(\"/optionMode\", false);\n\t\tconfigSettings->endGroup();\n\t\tconnect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));\n\t}\n\n\tfor (i = 0; i < colNr; i++)\n\t\tcolMap[i] = colRevMap[i] = -1;\n\taddColumn(promptColIdx, _(\"Option\"));\n\n\treinit();\n}\n\nbool ConfigList::menuSkip(struct menu *menu)\n{\n\tif (optMode == normalOpt && menu_is_visible(menu))\n\t\treturn false;\n\tif (optMode == promptOpt && menu_has_prompt(menu))\n\t\treturn false;\n\tif (optMode == allOpt)\n\t\treturn false;\n\treturn true;\n}\n\nvoid ConfigList::reinit(void)\n{\n\tremoveColumn(dataColIdx);\n\tremoveColumn(yesColIdx);\n\tremoveColumn(modColIdx);\n\tremoveColumn(noColIdx);\n\tremoveColumn(nameColIdx);\n\n\tif (showName)\n\t\taddColumn(nameColIdx, _(\"Name\"));\n\tif (showRange) {\n\t\taddColumn(noColIdx, \"N\");\n\t\taddColumn(modColIdx, \"M\");\n\t\taddColumn(yesColIdx, \"Y\");\n\t}\n\tif (showData)\n\t\taddColumn(dataColIdx, _(\"Value\"));\n\n\tupdateListAll();\n}\n\nvoid ConfigList::saveSettings(void)\n{\n\tif (name()) {\n\t\tconfigSettings->beginGroup(name());\n\t\tconfigSettings->writeEntry(\"/showName\", showName);\n\t\tconfigSettings->writeEntry(\"/showRange\", showRange);\n\t\tconfigSettings->writeEntry(\"/showData\", showData);\n\t\tconfigSettings->writeEntry(\"/optionMode\", (int)optMode);\n\t\tconfigSettings->endGroup();\n\t}\n}\n\nConfigItem* ConfigList::findConfigItem(struct menu *menu)\n{\n\tConfigItem* item = (ConfigItem*)menu->data;\n\n\tfor (; item; item = item->nextItem) {\n\t\tif (this == item->listView())\n\t\t\tbreak;\n\t}\n\n\treturn item;\n}\n\nvoid ConfigList::updateSelection(void)\n{\n\tstruct menu *menu;\n\tenum prop_type type;\n\n\tConfigItem* item = (ConfigItem*)selectedItem();\n\tif (!item)\n\t\treturn;\n\n\tmenu = item->menu;\n\temit menuChanged(menu);\n\tif (!menu)\n\t\treturn;\n\ttype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\tif (mode == menuMode && type == P_MENU)\n\t\temit menuSelected(menu);\n}\n\nvoid ConfigList::updateList(ConfigItem* item)\n{\n\tConfigItem* last = 0;\n\n\tif (!rootEntry) {\n\t\tif (mode != listMode)\n\t\t\tgoto update;\n\t\tQ3ListViewItemIterator it(this);\n\t\tConfigItem* item;\n\n\t\tfor (; it.current(); ++it) {\n\t\t\titem = (ConfigItem*)it.current();\n\t\t\tif (!item->menu)\n\t\t\t\tcontinue;\n\t\t\titem->testUpdateMenu(menu_is_visible(item->menu));\n\t\t}\n\t\treturn;\n\t}\n\n\tif (rootEntry != &rootmenu && (mode == singleMode ||\n\t    (mode == symbolMode && rootEntry->parent != &rootmenu))) {\n\t\titem = firstChild();\n\t\tif (!item)\n\t\t\titem = new ConfigItem(this, 0, true);\n\t\tlast = item;\n\t}\n\tif ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&\n\t    rootEntry->sym && rootEntry->prompt) {\n\t\titem = last ? last->nextSibling() : firstChild();\n\t\tif (!item)\n\t\t\titem = new ConfigItem(this, last, rootEntry, true);\n\t\telse\n\t\t\titem->testUpdateMenu(true);\n\n\t\tupdateMenuList(item, rootEntry);\n\t\ttriggerUpdate();\n\t\treturn;\n\t}\nupdate:\n\tupdateMenuList(this, rootEntry);\n\ttriggerUpdate();\n}\n\nvoid ConfigList::setValue(ConfigItem* item, tristate val)\n{\n\tstruct symbol* sym;\n\tint type;\n\ttristate oldval;\n\n\tsym = item->menu ? item->menu->sym : 0;\n\tif (!sym)\n\t\treturn;\n\n\ttype = sym_get_type(sym);\n\tswitch (type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\toldval = sym_get_tristate_value(sym);\n\n\t\tif (!sym_set_tristate_value(sym, val))\n\t\t\treturn;\n\t\tif (oldval == no && item->menu->list)\n\t\t\titem->setOpen(TRUE);\n\t\tparent()->updateList(item);\n\t\tbreak;\n\t}\n}\n\nvoid ConfigList::changeValue(ConfigItem* item)\n{\n\tstruct symbol* sym;\n\tstruct menu* menu;\n\tint type, oldexpr, newexpr;\n\n\tmenu = item->menu;\n\tif (!menu)\n\t\treturn;\n\tsym = menu->sym;\n\tif (!sym) {\n\t\tif (item->menu->list)\n\t\t\titem->setOpen(!item->isOpen());\n\t\treturn;\n\t}\n\n\ttype = sym_get_type(sym);\n\tswitch (type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\toldexpr = sym_get_tristate_value(sym);\n\t\tnewexpr = sym_toggle_tristate_value(sym);\n\t\tif (item->menu->list) {\n\t\t\tif (oldexpr == newexpr)\n\t\t\t\titem->setOpen(!item->isOpen());\n\t\t\telse if (oldexpr == no)\n\t\t\t\titem->setOpen(TRUE);\n\t\t}\n\t\tif (oldexpr != newexpr)\n\t\t\tparent()->updateList(item);\n\t\tbreak;\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tif (colMap[dataColIdx] >= 0)\n\t\t\titem->startRename(colMap[dataColIdx]);\n\t\telse\n\t\t\tparent()->lineEdit->show(item);\n\t\tbreak;\n\t}\n}\n\nvoid ConfigList::setRootMenu(struct menu *menu)\n{\n\tenum prop_type type;\n\n\tif (rootEntry == menu)\n\t\treturn;\n\ttype = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\tif (type != P_MENU)\n\t\treturn;\n\tupdateMenuList(this, 0);\n\trootEntry = menu;\n\tupdateListAll();\n\tsetSelected(currentItem(), hasFocus());\n\tensureItemVisible(currentItem());\n}\n\nvoid ConfigList::setParentMenu(void)\n{\n\tConfigItem* item;\n\tstruct menu *oldroot;\n\n\toldroot = rootEntry;\n\tif (rootEntry == &rootmenu)\n\t\treturn;\n\tsetRootMenu(menu_get_parent_menu(rootEntry->parent));\n\n\tQ3ListViewItemIterator it(this);\n\tfor (; (item = (ConfigItem*)it.current()); it++) {\n\t\tif (item->menu == oldroot) {\n\t\t\tsetCurrentItem(item);\n\t\t\tensureItemVisible(item);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/*\n * update all the children of a menu entry\n *   removes/adds the entries from the parent widget as necessary\n *\n * parent: either the menu list widget or a menu entry widget\n * menu: entry to be updated\n */\ntemplate <class P>\nvoid ConfigList::updateMenuList(P* parent, struct menu* menu)\n{\n\tstruct menu* child;\n\tConfigItem* item;\n\tConfigItem* last;\n\tbool visible;\n\tenum prop_type type;\n\n\tif (!menu) {\n\t\twhile ((item = parent->firstChild()))\n\t\t\tdelete item;\n\t\treturn;\n\t}\n\n\tlast = parent->firstChild();\n\tif (last && !last->goParent)\n\t\tlast = 0;\n\tfor (child = menu->list; child; child = child->next) {\n\t\titem = last ? last->nextSibling() : parent->firstChild();\n\t\ttype = child->prompt ? child->prompt->type : P_UNKNOWN;\n\n\t\tswitch (mode) {\n\t\tcase menuMode:\n\t\t\tif (!(child->flags & MENU_ROOT))\n\t\t\t\tgoto hide;\n\t\t\tbreak;\n\t\tcase symbolMode:\n\t\t\tif (child->flags & MENU_ROOT)\n\t\t\t\tgoto hide;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t\tvisible = menu_is_visible(child);\n\t\tif (!menuSkip(child)) {\n\t\t\tif (!child->sym && !child->list && !child->prompt)\n\t\t\t\tcontinue;\n\t\t\tif (!item || item->menu != child)\n\t\t\t\titem = new ConfigItem(parent, last, child, visible);\n\t\t\telse\n\t\t\t\titem->testUpdateMenu(visible);\n\n\t\t\tif (mode == fullMode || mode == menuMode || type != P_MENU)\n\t\t\t\tupdateMenuList(item, child);\n\t\t\telse\n\t\t\t\tupdateMenuList(item, 0);\n\t\t\tlast = item;\n\t\t\tcontinue;\n\t\t}\n\thide:\n\t\tif (item && item->menu == child) {\n\t\t\tlast = parent->firstChild();\n\t\t\tif (last == item)\n\t\t\t\tlast = 0;\n\t\t\telse while (last->nextSibling() != item)\n\t\t\t\tlast = last->nextSibling();\n\t\t\tdelete item;\n\t\t}\n\t}\n}\n\nvoid ConfigList::keyPressEvent(QKeyEvent* ev)\n{\n\tQ3ListViewItem* i = currentItem();\n\tConfigItem* item;\n\tstruct menu *menu;\n\tenum prop_type type;\n\n\tif (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {\n\t\temit parentSelected();\n\t\tev->accept();\n\t\treturn;\n\t}\n\n\tif (!i) {\n\t\tParent::keyPressEvent(ev);\n\t\treturn;\n\t}\n\titem = (ConfigItem*)i;\n\n\tswitch (ev->key()) {\n\tcase Qt::Key_Return:\n\tcase Qt::Key_Enter:\n\t\tif (item->goParent) {\n\t\t\temit parentSelected();\n\t\t\tbreak;\n\t\t}\n\t\tmenu = item->menu;\n\t\tif (!menu)\n\t\t\tbreak;\n\t\ttype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\t\tif (type == P_MENU && rootEntry != menu &&\n\t\t    mode != fullMode && mode != menuMode) {\n\t\t\temit menuSelected(menu);\n\t\t\tbreak;\n\t\t}\n\tcase Qt::Key_Space:\n\t\tchangeValue(item);\n\t\tbreak;\n\tcase Qt::Key_N:\n\t\tsetValue(item, no);\n\t\tbreak;\n\tcase Qt::Key_M:\n\t\tsetValue(item, mod);\n\t\tbreak;\n\tcase Qt::Key_Y:\n\t\tsetValue(item, yes);\n\t\tbreak;\n\tdefault:\n\t\tParent::keyPressEvent(ev);\n\t\treturn;\n\t}\n\tev->accept();\n}\n\nvoid ConfigList::contentsMousePressEvent(QMouseEvent* e)\n{\n\t//QPoint p(contentsToViewport(e->pos()));\n\t//printf(\"contentsMousePressEvent: %d,%d\\n\", p.x(), p.y());\n\tParent::contentsMousePressEvent(e);\n}\n\nvoid ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)\n{\n\tQPoint p(contentsToViewport(e->pos()));\n\tConfigItem* item = (ConfigItem*)itemAt(p);\n\tstruct menu *menu;\n\tenum prop_type ptype;\n\tconst QPixmap* pm;\n\tint idx, x;\n\n\tif (!item)\n\t\tgoto skip;\n\n\tmenu = item->menu;\n\tx = header()->offset() + p.x();\n\tidx = colRevMap[header()->sectionAt(x)];\n\tswitch (idx) {\n\tcase promptColIdx:\n\t\tpm = item->pixmap(promptColIdx);\n\t\tif (pm) {\n\t\t\tint off = header()->sectionPos(0) + itemMargin() +\n\t\t\t\ttreeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));\n\t\t\tif (x >= off && x < off + pm->width()) {\n\t\t\t\tif (item->goParent) {\n\t\t\t\t\temit parentSelected();\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (!menu)\n\t\t\t\t\tbreak;\n\t\t\t\tptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\t\t\t\tif (ptype == P_MENU && rootEntry != menu &&\n\t\t\t\t    mode != fullMode && mode != menuMode)\n\t\t\t\t\temit menuSelected(menu);\n\t\t\t\telse\n\t\t\t\t\tchangeValue(item);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase noColIdx:\n\t\tsetValue(item, no);\n\t\tbreak;\n\tcase modColIdx:\n\t\tsetValue(item, mod);\n\t\tbreak;\n\tcase yesColIdx:\n\t\tsetValue(item, yes);\n\t\tbreak;\n\tcase dataColIdx:\n\t\tchangeValue(item);\n\t\tbreak;\n\t}\n\nskip:\n\t//printf(\"contentsMouseReleaseEvent: %d,%d\\n\", p.x(), p.y());\n\tParent::contentsMouseReleaseEvent(e);\n}\n\nvoid ConfigList::contentsMouseMoveEvent(QMouseEvent* e)\n{\n\t//QPoint p(contentsToViewport(e->pos()));\n\t//printf(\"contentsMouseMoveEvent: %d,%d\\n\", p.x(), p.y());\n\tParent::contentsMouseMoveEvent(e);\n}\n\nvoid ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)\n{\n\tQPoint p(contentsToViewport(e->pos()));\n\tConfigItem* item = (ConfigItem*)itemAt(p);\n\tstruct menu *menu;\n\tenum prop_type ptype;\n\n\tif (!item)\n\t\tgoto skip;\n\tif (item->goParent) {\n\t\temit parentSelected();\n\t\tgoto skip;\n\t}\n\tmenu = item->menu;\n\tif (!menu)\n\t\tgoto skip;\n\tptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\tif (ptype == P_MENU && (mode == singleMode || mode == symbolMode))\n\t\temit menuSelected(menu);\n\telse if (menu->sym)\n\t\tchangeValue(item);\n\nskip:\n\t//printf(\"contentsMouseDoubleClickEvent: %d,%d\\n\", p.x(), p.y());\n\tParent::contentsMouseDoubleClickEvent(e);\n}\n\nvoid ConfigList::focusInEvent(QFocusEvent *e)\n{\n\tstruct menu *menu = NULL;\n\n\tParent::focusInEvent(e);\n\n\tConfigItem* item = (ConfigItem *)currentItem();\n\tif (item) {\n\t\tsetSelected(item, TRUE);\n\t\tmenu = item->menu;\n\t}\n\temit gotFocus(menu);\n}\n\nvoid ConfigList::contextMenuEvent(QContextMenuEvent *e)\n{\n\tif (e->y() <= header()->geometry().bottom()) {\n\t\tif (!headerPopup) {\n\t\t\tQ3Action *action;\n\n\t\t\theaderPopup = new Q3PopupMenu(this);\n\t\t\taction = new Q3Action(NULL, _(\"Show Name\"), 0, this);\n\t\t\t  action->setToggleAction(TRUE);\n\t\t\t  connect(action, SIGNAL(toggled(bool)),\n\t\t\t\t  parent(), SLOT(setShowName(bool)));\n\t\t\t  connect(parent(), SIGNAL(showNameChanged(bool)),\n\t\t\t\t  action, SLOT(setOn(bool)));\n\t\t\t  action->setOn(showName);\n\t\t\t  action->addTo(headerPopup);\n\t\t\taction = new Q3Action(NULL, _(\"Show Range\"), 0, this);\n\t\t\t  action->setToggleAction(TRUE);\n\t\t\t  connect(action, SIGNAL(toggled(bool)),\n\t\t\t\t  parent(), SLOT(setShowRange(bool)));\n\t\t\t  connect(parent(), SIGNAL(showRangeChanged(bool)),\n\t\t\t\t  action, SLOT(setOn(bool)));\n\t\t\t  action->setOn(showRange);\n\t\t\t  action->addTo(headerPopup);\n\t\t\taction = new Q3Action(NULL, _(\"Show Data\"), 0, this);\n\t\t\t  action->setToggleAction(TRUE);\n\t\t\t  connect(action, SIGNAL(toggled(bool)),\n\t\t\t\t  parent(), SLOT(setShowData(bool)));\n\t\t\t  connect(parent(), SIGNAL(showDataChanged(bool)),\n\t\t\t\t  action, SLOT(setOn(bool)));\n\t\t\t  action->setOn(showData);\n\t\t\t  action->addTo(headerPopup);\n\t\t}\n\t\theaderPopup->exec(e->globalPos());\n\t\te->accept();\n\t} else\n\t\te->ignore();\n}\n\nConfigView*ConfigView::viewList;\nQAction *ConfigView::showNormalAction;\nQAction *ConfigView::showAllAction;\nQAction *ConfigView::showPromptAction;\n\nConfigView::ConfigView(QWidget* parent, const char *name)\n\t: Parent(parent, name)\n{\n\tlist = new ConfigList(this, name);\n\tlineEdit = new ConfigLineEdit(this);\n\tlineEdit->hide();\n\n\tthis->nextView = viewList;\n\tviewList = this;\n}\n\nConfigView::~ConfigView(void)\n{\n\tConfigView** vp;\n\n\tfor (vp = &viewList; *vp; vp = &(*vp)->nextView) {\n\t\tif (*vp == this) {\n\t\t\t*vp = nextView;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid ConfigView::setOptionMode(QAction *act)\n{\n\tif (act == showNormalAction)\n\t\tlist->optMode = normalOpt;\n\telse if (act == showAllAction)\n\t\tlist->optMode = allOpt;\n\telse\n\t\tlist->optMode = promptOpt;\n\n\tlist->updateListAll();\n}\n\nvoid ConfigView::setShowName(bool b)\n{\n\tif (list->showName != b) {\n\t\tlist->showName = b;\n\t\tlist->reinit();\n\t\temit showNameChanged(b);\n\t}\n}\n\nvoid ConfigView::setShowRange(bool b)\n{\n\tif (list->showRange != b) {\n\t\tlist->showRange = b;\n\t\tlist->reinit();\n\t\temit showRangeChanged(b);\n\t}\n}\n\nvoid ConfigView::setShowData(bool b)\n{\n\tif (list->showData != b) {\n\t\tlist->showData = b;\n\t\tlist->reinit();\n\t\temit showDataChanged(b);\n\t}\n}\n\nvoid ConfigList::setAllOpen(bool open)\n{\n\tQ3ListViewItemIterator it(this);\n\n\tfor (; it.current(); it++)\n\t\tit.current()->setOpen(open);\n}\n\nvoid ConfigView::updateList(ConfigItem* item)\n{\n\tConfigView* v;\n\n\tfor (v = viewList; v; v = v->nextView)\n\t\tv->list->updateList(item);\n}\n\nvoid ConfigView::updateListAll(void)\n{\n\tConfigView* v;\n\n\tfor (v = viewList; v; v = v->nextView)\n\t\tv->list->updateListAll();\n}\n\nConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)\n\t: Parent(parent, name), sym(0), _menu(0)\n{\n\tif (name) {\n\t\tconfigSettings->beginGroup(name);\n\t\t_showDebug = configSettings->readBoolEntry(\"/showDebug\", false);\n\t\tconfigSettings->endGroup();\n\t\tconnect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));\n\t}\n}\n\nvoid ConfigInfoView::saveSettings(void)\n{\n\tif (name()) {\n\t\tconfigSettings->beginGroup(name());\n\t\tconfigSettings->writeEntry(\"/showDebug\", showDebug());\n\t\tconfigSettings->endGroup();\n\t}\n}\n\nvoid ConfigInfoView::setShowDebug(bool b)\n{\n\tif (_showDebug != b) {\n\t\t_showDebug = b;\n\t\tif (_menu)\n\t\t\tmenuInfo();\n\t\telse if (sym)\n\t\t\tsymbolInfo();\n\t\temit showDebugChanged(b);\n\t}\n}\n\nvoid ConfigInfoView::setInfo(struct menu *m)\n{\n\tif (_menu == m)\n\t\treturn;\n\t_menu = m;\n\tsym = NULL;\n\tif (!_menu)\n\t\tclear();\n\telse\n\t\tmenuInfo();\n}\n\nvoid ConfigInfoView::symbolInfo(void)\n{\n\tQString str;\n\n\tstr += \"<big>Symbol: <b>\";\n\tstr += print_filter(sym->name);\n\tstr += \"</b></big><br><br>value: \";\n\tstr += print_filter(sym_get_string_value(sym));\n\tstr += \"<br>visibility: \";\n\tstr += sym->visible == yes ? \"y\" : sym->visible == mod ? \"m\" : \"n\";\n\tstr += \"<br>\";\n\tstr += debug_info(sym);\n\n\tsetText(str);\n}\n\nvoid ConfigInfoView::menuInfo(void)\n{\n\tstruct symbol* sym;\n\tQString head, debug, help;\n\n\tsym = _menu->sym;\n\tif (sym) {\n\t\tif (_menu->prompt) {\n\t\t\thead += \"<big><b>\";\n\t\t\thead += print_filter(_(_menu->prompt->text));\n\t\t\thead += \"</b></big>\";\n\t\t\tif (sym->name) {\n\t\t\t\thead += \" (\";\n\t\t\t\tif (showDebug())\n\t\t\t\t\thead += QString().sprintf(\"<a href=\\\"s%p\\\">\", sym);\n\t\t\t\thead += print_filter(sym->name);\n\t\t\t\tif (showDebug())\n\t\t\t\t\thead += \"</a>\";\n\t\t\t\thead += \")\";\n\t\t\t}\n\t\t} else if (sym->name) {\n\t\t\thead += \"<big><b>\";\n\t\t\tif (showDebug())\n\t\t\t\thead += QString().sprintf(\"<a href=\\\"s%p\\\">\", sym);\n\t\t\thead += print_filter(sym->name);\n\t\t\tif (showDebug())\n\t\t\t\thead += \"</a>\";\n\t\t\thead += \"</b></big>\";\n\t\t}\n\t\thead += \"<br><br>\";\n\n\t\tif (showDebug())\n\t\t\tdebug = debug_info(sym);\n\n\t\tstruct gstr help_gstr = str_new();\n\t\tmenu_get_ext_help(_menu, &help_gstr);\n\t\thelp = print_filter(str_get(&help_gstr));\n\t\tstr_free(&help_gstr);\n\t} else if (_menu->prompt) {\n\t\thead += \"<big><b>\";\n\t\thead += print_filter(_(_menu->prompt->text));\n\t\thead += \"</b></big><br><br>\";\n\t\tif (showDebug()) {\n\t\t\tif (_menu->prompt->visible.expr) {\n\t\t\t\tdebug += \"&nbsp;&nbsp;dep: \";\n\t\t\t\texpr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);\n\t\t\t\tdebug += \"<br><br>\";\n\t\t\t}\n\t\t}\n\t}\n\tif (showDebug())\n\t\tdebug += QString().sprintf(\"defined at %s:%d<br><br>\", _menu->file->name, _menu->lineno);\n\n\tsetText(head + debug + help);\n}\n\nQString ConfigInfoView::debug_info(struct symbol *sym)\n{\n\tQString debug;\n\n\tdebug += \"type: \";\n\tdebug += print_filter(sym_type_name(sym->type));\n\tif (sym_is_choice(sym))\n\t\tdebug += \" (choice)\";\n\tdebug += \"<br>\";\n\tif (sym->rev_dep.expr) {\n\t\tdebug += \"reverse dep: \";\n\t\texpr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);\n\t\tdebug += \"<br>\";\n\t}\n\tfor (struct property *prop = sym->prop; prop; prop = prop->next) {\n\t\tswitch (prop->type) {\n\t\tcase P_PROMPT:\n\t\tcase P_MENU:\n\t\t\tdebug += QString().sprintf(\"prompt: <a href=\\\"m%p\\\">\", prop->menu);\n\t\t\tdebug += print_filter(_(prop->text));\n\t\t\tdebug += \"</a><br>\";\n\t\t\tbreak;\n\t\tcase P_DEFAULT:\n\t\tcase P_SELECT:\n\t\tcase P_RANGE:\n\t\tcase P_ENV:\n\t\t\tdebug += prop_get_type_name(prop->type);\n\t\t\tdebug += \": \";\n\t\t\texpr_print(prop->expr, expr_print_help, &debug, E_NONE);\n\t\t\tdebug += \"<br>\";\n\t\t\tbreak;\n\t\tcase P_CHOICE:\n\t\t\tif (sym_is_choice(sym)) {\n\t\t\t\tdebug += \"choice: \";\n\t\t\t\texpr_print(prop->expr, expr_print_help, &debug, E_NONE);\n\t\t\t\tdebug += \"<br>\";\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tdebug += \"unknown property: \";\n\t\t\tdebug += prop_get_type_name(prop->type);\n\t\t\tdebug += \"<br>\";\n\t\t}\n\t\tif (prop->visible.expr) {\n\t\t\tdebug += \"&nbsp;&nbsp;&nbsp;&nbsp;dep: \";\n\t\t\texpr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);\n\t\t\tdebug += \"<br>\";\n\t\t}\n\t}\n\tdebug += \"<br>\";\n\n\treturn debug;\n}\n\nQString ConfigInfoView::print_filter(const QString &str)\n{\n\tQRegExp re(\"[<>&\\\"\\\\n]\");\n\tQString res = str;\n\tfor (int i = 0; (i = res.find(re, i)) >= 0;) {\n\t\tswitch (res[i].latin1()) {\n\t\tcase '<':\n\t\t\tres.replace(i, 1, \"&lt;\");\n\t\t\ti += 4;\n\t\t\tbreak;\n\t\tcase '>':\n\t\t\tres.replace(i, 1, \"&gt;\");\n\t\t\ti += 4;\n\t\t\tbreak;\n\t\tcase '&':\n\t\t\tres.replace(i, 1, \"&amp;\");\n\t\t\ti += 5;\n\t\t\tbreak;\n\t\tcase '\"':\n\t\t\tres.replace(i, 1, \"&quot;\");\n\t\t\ti += 6;\n\t\t\tbreak;\n\t\tcase '\\n':\n\t\t\tres.replace(i, 1, \"<br>\");\n\t\t\ti += 4;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn res;\n}\n\nvoid ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)\n{\n\tQString* text = reinterpret_cast<QString*>(data);\n\tQString str2 = print_filter(str);\n\n\tif (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {\n\t\t*text += QString().sprintf(\"<a href=\\\"s%p\\\">\", sym);\n\t\t*text += str2;\n\t\t*text += \"</a>\";\n\t} else\n\t\t*text += str2;\n}\n\nQ3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)\n{\n\tQ3PopupMenu* popup = Parent::createPopupMenu(pos);\n\tQ3Action* action = new Q3Action(NULL, _(\"Show Debug Info\"), 0, popup);\n\t  action->setToggleAction(TRUE);\n\t  connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));\n\t  connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));\n\t  action->setOn(showDebug());\n\tpopup->insertSeparator();\n\taction->addTo(popup);\n\treturn popup;\n}\n\nvoid ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)\n{\n\tParent::contentsContextMenuEvent(e);\n}\n\nConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name)\n\t: Parent(parent, name), result(NULL)\n{\n\tsetCaption(\"Search Config\");\n\n\tQVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);\n\tQHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);\n\tlayout2->addWidget(new QLabel(_(\"Find:\"), this));\n\teditField = new QLineEdit(this);\n\tconnect(editField, SIGNAL(returnPressed()), SLOT(search()));\n\tlayout2->addWidget(editField);\n\tsearchButton = new QPushButton(_(\"Search\"), this);\n\tsearchButton->setAutoDefault(FALSE);\n\tconnect(searchButton, SIGNAL(clicked()), SLOT(search()));\n\tlayout2->addWidget(searchButton);\n\tlayout1->addLayout(layout2);\n\n\tsplit = new QSplitter(this);\n\tsplit->setOrientation(Qt::Vertical);\n\tlist = new ConfigView(split, name);\n\tlist->list->mode = listMode;\n\tinfo = new ConfigInfoView(split, name);\n\tconnect(list->list, SIGNAL(menuChanged(struct menu *)),\n\t\tinfo, SLOT(setInfo(struct menu *)));\n\tconnect(list->list, SIGNAL(menuChanged(struct menu *)),\n\t\tparent, SLOT(setMenuLink(struct menu *)));\n\n\tlayout1->addWidget(split);\n\n\tif (name) {\n\t\tint x, y, width, height;\n\t\tbool ok;\n\n\t\tconfigSettings->beginGroup(name);\n\t\twidth = configSettings->readNumEntry(\"/window width\", parent->width() / 2);\n\t\theight = configSettings->readNumEntry(\"/window height\", parent->height() / 2);\n\t\tresize(width, height);\n\t\tx = configSettings->readNumEntry(\"/window x\", 0, &ok);\n\t\tif (ok)\n\t\t\ty = configSettings->readNumEntry(\"/window y\", 0, &ok);\n\t\tif (ok)\n\t\t\tmove(x, y);\n\t\tQ3ValueList<int> sizes = configSettings->readSizes(\"/split\", &ok);\n\t\tif (ok)\n\t\t\tsplit->setSizes(sizes);\n\t\tconfigSettings->endGroup();\n\t\tconnect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));\n\t}\n}\n\nvoid ConfigSearchWindow::saveSettings(void)\n{\n\tif (name()) {\n\t\tconfigSettings->beginGroup(name());\n\t\tconfigSettings->writeEntry(\"/window x\", pos().x());\n\t\tconfigSettings->writeEntry(\"/window y\", pos().y());\n\t\tconfigSettings->writeEntry(\"/window width\", size().width());\n\t\tconfigSettings->writeEntry(\"/window height\", size().height());\n\t\tconfigSettings->writeSizes(\"/split\", split->sizes());\n\t\tconfigSettings->endGroup();\n\t}\n}\n\nvoid ConfigSearchWindow::search(void)\n{\n\tstruct symbol **p;\n\tstruct property *prop;\n\tConfigItem *lastItem = NULL;\n\n\tfree(result);\n\tlist->list->clear();\n\tinfo->clear();\n\n\tresult = sym_re_search(editField->text().latin1());\n\tif (!result)\n\t\treturn;\n\tfor (p = result; *p; p++) {\n\t\tfor_all_prompts((*p), prop)\n\t\t\tlastItem = new ConfigItem(list->list, lastItem, prop->menu,\n\t\t\t\t\t\t  menu_is_visible(prop->menu));\n\t}\n}\n\n/*\n * Construct the complete config widget\n */\nConfigMainWindow::ConfigMainWindow(void)\n\t: searchWindow(0)\n{\n\tQMenuBar* menu;\n\tbool ok;\n\tint x, y, width, height;\n\tchar title[256];\n\n\tQDesktopWidget *d = configApp->desktop();\n\tsnprintf(title, sizeof(title), \"%s%s\",\n\t\trootmenu.prompt->text,\n#if QT_VERSION < 0x040000\n\t\t\" (Qt3)\"\n#else\n\t\t\"\"\n#endif\n\t\t);\n\tsetCaption(title);\n\n\twidth = configSettings->readNumEntry(\"/window width\", d->width() - 64);\n\theight = configSettings->readNumEntry(\"/window height\", d->height() - 64);\n\tresize(width, height);\n\tx = configSettings->readNumEntry(\"/window x\", 0, &ok);\n\tif (ok)\n\t\ty = configSettings->readNumEntry(\"/window y\", 0, &ok);\n\tif (ok)\n\t\tmove(x, y);\n\n\tsplit1 = new QSplitter(this);\n\tsplit1->setOrientation(Qt::Horizontal);\n\tsetCentralWidget(split1);\n\n\tmenuView = new ConfigView(split1, \"menu\");\n\tmenuList = menuView->list;\n\n\tsplit2 = new QSplitter(split1);\n\tsplit2->setOrientation(Qt::Vertical);\n\n\t// create config tree\n\tconfigView = new ConfigView(split2, \"config\");\n\tconfigList = configView->list;\n\n\thelpText = new ConfigInfoView(split2, \"help\");\n\thelpText->setTextFormat(Qt::RichText);\n\n\tsetTabOrder(configList, helpText);\n\tconfigList->setFocus();\n\n\tmenu = menuBar();\n\ttoolBar = new Q3ToolBar(\"Tools\", this);\n\n\tbackAction = new Q3Action(\"Back\", QPixmap(xpm_back), _(\"Back\"), 0, this);\n\t  connect(backAction, SIGNAL(activated()), SLOT(goBack()));\n\t  backAction->setEnabled(FALSE);\n\tQ3Action *quitAction = new Q3Action(\"Quit\", _(\"&Quit\"), Qt::CTRL + Qt::Key_Q, this);\n\t  connect(quitAction, SIGNAL(activated()), SLOT(close()));\n\tQ3Action *loadAction = new Q3Action(\"Load\", QPixmap(xpm_load), _(\"&Load\"), Qt::CTRL + Qt::Key_L, this);\n\t  connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));\n\tsaveAction = new Q3Action(\"Save\", QPixmap(xpm_save), _(\"&Save\"), Qt::CTRL + Qt::Key_S, this);\n\t  connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));\n\tconf_set_changed_callback(conf_changed);\n\t// Set saveAction's initial state\n\tconf_changed();\n\tQ3Action *saveAsAction = new Q3Action(\"Save As...\", _(\"Save &As...\"), 0, this);\n\t  connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));\n\tQ3Action *searchAction = new Q3Action(\"Find\", _(\"&Find\"), Qt::CTRL + Qt::Key_F, this);\n\t  connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));\n\tQ3Action *singleViewAction = new Q3Action(\"Single View\", QPixmap(xpm_single_view), _(\"Single View\"), 0, this);\n\t  connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));\n\tQ3Action *splitViewAction = new Q3Action(\"Split View\", QPixmap(xpm_split_view), _(\"Split View\"), 0, this);\n\t  connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));\n\tQ3Action *fullViewAction = new Q3Action(\"Full View\", QPixmap(xpm_tree_view), _(\"Full View\"), 0, this);\n\t  connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));\n\n\tQ3Action *showNameAction = new Q3Action(NULL, _(\"Show Name\"), 0, this);\n\t  showNameAction->setToggleAction(TRUE);\n\t  connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));\n\t  connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));\n\t  showNameAction->setOn(configView->showName());\n\tQ3Action *showRangeAction = new Q3Action(NULL, _(\"Show Range\"), 0, this);\n\t  showRangeAction->setToggleAction(TRUE);\n\t  connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));\n\t  connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));\n\t  showRangeAction->setOn(configList->showRange);\n\tQ3Action *showDataAction = new Q3Action(NULL, _(\"Show Data\"), 0, this);\n\t  showDataAction->setToggleAction(TRUE);\n\t  connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));\n\t  connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));\n\t  showDataAction->setOn(configList->showData);\n\n\tQActionGroup *optGroup = new QActionGroup(this);\n\toptGroup->setExclusive(TRUE);\n\tconnect(optGroup, SIGNAL(selected(QAction *)), configView,\n\t\tSLOT(setOptionMode(QAction *)));\n\tconnect(optGroup, SIGNAL(selected(QAction *)), menuView,\n\t\tSLOT(setOptionMode(QAction *)));\n\n#if QT_VERSION >= 0x040000\n\tconfigView->showNormalAction = new QAction(_(\"Show Normal Options\"), optGroup);\n\tconfigView->showAllAction = new QAction(_(\"Show All Options\"), optGroup);\n\tconfigView->showPromptAction = new QAction(_(\"Show Prompt Options\"), optGroup);\n#else\n\tconfigView->showNormalAction = new QAction(_(\"Show Normal Options\"), 0, optGroup);\n\tconfigView->showAllAction = new QAction(_(\"Show All Options\"), 0, optGroup);\n\tconfigView->showPromptAction = new QAction(_(\"Show Prompt Options\"), 0, optGroup);\n#endif\n\tconfigView->showNormalAction->setToggleAction(TRUE);\n\tconfigView->showNormalAction->setOn(configList->optMode == normalOpt);\n\tconfigView->showAllAction->setToggleAction(TRUE);\n\tconfigView->showAllAction->setOn(configList->optMode == allOpt);\n\tconfigView->showPromptAction->setToggleAction(TRUE);\n\tconfigView->showPromptAction->setOn(configList->optMode == promptOpt);\n\n\tQ3Action *showDebugAction = new Q3Action(NULL, _(\"Show Debug Info\"), 0, this);\n\t  showDebugAction->setToggleAction(TRUE);\n\t  connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));\n\t  connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));\n\t  showDebugAction->setOn(helpText->showDebug());\n\n\tQ3Action *showIntroAction = new Q3Action(NULL, _(\"Introduction\"), 0, this);\n\t  connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));\n\tQ3Action *showAboutAction = new Q3Action(NULL, _(\"About\"), 0, this);\n\t  connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));\n\n\t// init tool bar\n\tbackAction->addTo(toolBar);\n\ttoolBar->addSeparator();\n\tloadAction->addTo(toolBar);\n\tsaveAction->addTo(toolBar);\n\ttoolBar->addSeparator();\n\tsingleViewAction->addTo(toolBar);\n\tsplitViewAction->addTo(toolBar);\n\tfullViewAction->addTo(toolBar);\n\n\t// create config menu\n\tQ3PopupMenu* config = new Q3PopupMenu(this);\n\tmenu->insertItem(_(\"&File\"), config);\n\tloadAction->addTo(config);\n\tsaveAction->addTo(config);\n\tsaveAsAction->addTo(config);\n\tconfig->insertSeparator();\n\tquitAction->addTo(config);\n\n\t// create edit menu\n\tQ3PopupMenu* editMenu = new Q3PopupMenu(this);\n\tmenu->insertItem(_(\"&Edit\"), editMenu);\n\tsearchAction->addTo(editMenu);\n\n\t// create options menu\n\tQ3PopupMenu* optionMenu = new Q3PopupMenu(this);\n\tmenu->insertItem(_(\"&Option\"), optionMenu);\n\tshowNameAction->addTo(optionMenu);\n\tshowRangeAction->addTo(optionMenu);\n\tshowDataAction->addTo(optionMenu);\n\toptionMenu->insertSeparator();\n\toptGroup->addTo(optionMenu);\n\toptionMenu->insertSeparator();\n\n\t// create help menu\n\tQ3PopupMenu* helpMenu = new Q3PopupMenu(this);\n\tmenu->insertSeparator();\n\tmenu->insertItem(_(\"&Help\"), helpMenu);\n\tshowIntroAction->addTo(helpMenu);\n\tshowAboutAction->addTo(helpMenu);\n\n\tconnect(configList, SIGNAL(menuChanged(struct menu *)),\n\t\thelpText, SLOT(setInfo(struct menu *)));\n\tconnect(configList, SIGNAL(menuSelected(struct menu *)),\n\t\tSLOT(changeMenu(struct menu *)));\n\tconnect(configList, SIGNAL(parentSelected()),\n\t\tSLOT(goBack()));\n\tconnect(menuList, SIGNAL(menuChanged(struct menu *)),\n\t\thelpText, SLOT(setInfo(struct menu *)));\n\tconnect(menuList, SIGNAL(menuSelected(struct menu *)),\n\t\tSLOT(changeMenu(struct menu *)));\n\n\tconnect(configList, SIGNAL(gotFocus(struct menu *)),\n\t\thelpText, SLOT(setInfo(struct menu *)));\n\tconnect(menuList, SIGNAL(gotFocus(struct menu *)),\n\t\thelpText, SLOT(setInfo(struct menu *)));\n\tconnect(menuList, SIGNAL(gotFocus(struct menu *)),\n\t\tSLOT(listFocusChanged(void)));\n\tconnect(helpText, SIGNAL(menuSelected(struct menu *)),\n\t\tSLOT(setMenuLink(struct menu *)));\n\n\tQString listMode = configSettings->readEntry(\"/listMode\", \"symbol\");\n\tif (listMode == \"single\")\n\t\tshowSingleView();\n\telse if (listMode == \"full\")\n\t\tshowFullView();\n\telse /*if (listMode == \"split\")*/\n\t\tshowSplitView();\n\n\t// UI setup done, restore splitter positions\n\tQ3ValueList<int> sizes = configSettings->readSizes(\"/split1\", &ok);\n\tif (ok)\n\t\tsplit1->setSizes(sizes);\n\n\tsizes = configSettings->readSizes(\"/split2\", &ok);\n\tif (ok)\n\t\tsplit2->setSizes(sizes);\n}\n\nvoid ConfigMainWindow::loadConfig(void)\n{\n\tQString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);\n\tif (s.isNull())\n\t\treturn;\n\tif (conf_read(QFile::encodeName(s)))\n\t\tQMessageBox::information(this, \"qconf\", _(\"Unable to load configuration!\"));\n\tConfigView::updateListAll();\n}\n\nbool ConfigMainWindow::saveConfig(void)\n{\n\tif (conf_write(NULL)) {\n\t\tQMessageBox::information(this, \"qconf\", _(\"Unable to save configuration!\"));\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nvoid ConfigMainWindow::saveConfigAs(void)\n{\n\tQString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);\n\tif (s.isNull())\n\t\treturn;\n\tsaveConfig();\n}\n\nvoid ConfigMainWindow::searchConfig(void)\n{\n\tif (!searchWindow)\n\t\tsearchWindow = new ConfigSearchWindow(this, \"search\");\n\tsearchWindow->show();\n}\n\nvoid ConfigMainWindow::changeMenu(struct menu *menu)\n{\n\tconfigList->setRootMenu(menu);\n\tif (configList->rootEntry->parent == &rootmenu)\n\t\tbackAction->setEnabled(FALSE);\n\telse\n\t\tbackAction->setEnabled(TRUE);\n}\n\nvoid ConfigMainWindow::setMenuLink(struct menu *menu)\n{\n\tstruct menu *parent;\n\tConfigList* list = NULL;\n\tConfigItem* item;\n\n\tif (configList->menuSkip(menu))\n\t\treturn;\n\n\tswitch (configList->mode) {\n\tcase singleMode:\n\t\tlist = configList;\n\t\tparent = menu_get_parent_menu(menu);\n\t\tif (!parent)\n\t\t\treturn;\n\t\tlist->setRootMenu(parent);\n\t\tbreak;\n\tcase symbolMode:\n\t\tif (menu->flags & MENU_ROOT) {\n\t\t\tconfigList->setRootMenu(menu);\n\t\t\tconfigList->clearSelection();\n\t\t\tlist = menuList;\n\t\t} else {\n\t\t\tlist = configList;\n\t\t\tparent = menu_get_parent_menu(menu->parent);\n\t\t\tif (!parent)\n\t\t\t\treturn;\n\t\t\titem = menuList->findConfigItem(parent);\n\t\t\tif (item) {\n\t\t\t\tmenuList->setSelected(item, TRUE);\n\t\t\t\tmenuList->ensureItemVisible(item);\n\t\t\t}\n\t\t\tlist->setRootMenu(parent);\n\t\t}\n\t\tbreak;\n\tcase fullMode:\n\t\tlist = configList;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tif (list) {\n\t\titem = list->findConfigItem(menu);\n\t\tif (item) {\n\t\t\tlist->setSelected(item, TRUE);\n\t\t\tlist->ensureItemVisible(item);\n\t\t\tlist->setFocus();\n\t\t}\n\t}\n}\n\nvoid ConfigMainWindow::listFocusChanged(void)\n{\n\tif (menuList->mode == menuMode)\n\t\tconfigList->clearSelection();\n}\n\nvoid ConfigMainWindow::goBack(void)\n{\n\tConfigItem* item;\n\n\tconfigList->setParentMenu();\n\tif (configList->rootEntry == &rootmenu)\n\t\tbackAction->setEnabled(FALSE);\n\titem = (ConfigItem*)menuList->selectedItem();\n\twhile (item) {\n\t\tif (item->menu == configList->rootEntry) {\n\t\t\tmenuList->setSelected(item, TRUE);\n\t\t\tbreak;\n\t\t}\n\t\titem = (ConfigItem*)item->parent();\n\t}\n}\n\nvoid ConfigMainWindow::showSingleView(void)\n{\n\tmenuView->hide();\n\tmenuList->setRootMenu(0);\n\tconfigList->mode = singleMode;\n\tif (configList->rootEntry == &rootmenu)\n\t\tconfigList->updateListAll();\n\telse\n\t\tconfigList->setRootMenu(&rootmenu);\n\tconfigList->setAllOpen(TRUE);\n\tconfigList->setFocus();\n}\n\nvoid ConfigMainWindow::showSplitView(void)\n{\n\tconfigList->mode = symbolMode;\n\tif (configList->rootEntry == &rootmenu)\n\t\tconfigList->updateListAll();\n\telse\n\t\tconfigList->setRootMenu(&rootmenu);\n\tconfigList->setAllOpen(TRUE);\n\tconfigApp->processEvents();\n\tmenuList->mode = menuMode;\n\tmenuList->setRootMenu(&rootmenu);\n\tmenuList->setAllOpen(TRUE);\n\tmenuView->show();\n\tmenuList->setFocus();\n}\n\nvoid ConfigMainWindow::showFullView(void)\n{\n\tmenuView->hide();\n\tmenuList->setRootMenu(0);\n\tconfigList->mode = fullMode;\n\tif (configList->rootEntry == &rootmenu)\n\t\tconfigList->updateListAll();\n\telse\n\t\tconfigList->setRootMenu(&rootmenu);\n\tconfigList->setAllOpen(FALSE);\n\tconfigList->setFocus();\n}\n\n/*\n * ask for saving configuration before quitting\n * TODO ask only when something changed\n */\nvoid ConfigMainWindow::closeEvent(QCloseEvent* e)\n{\n\tif (!conf_get_changed()) {\n\t\te->accept();\n\t\treturn;\n\t}\n\tQMessageBox mb(\"qconf\", _(\"Save configuration?\"), QMessageBox::Warning,\n\t\t\tQMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);\n\tmb.setButtonText(QMessageBox::Yes, _(\"&Save Changes\"));\n\tmb.setButtonText(QMessageBox::No, _(\"&Discard Changes\"));\n\tmb.setButtonText(QMessageBox::Cancel, _(\"Cancel Exit\"));\n\tswitch (mb.exec()) {\n\tcase QMessageBox::Yes:\n\t\tif (saveConfig())\n\t\t\te->accept();\n\t\telse\n\t\t\te->ignore();\n\t\tbreak;\n\tcase QMessageBox::No:\n\t\te->accept();\n\t\tbreak;\n\tcase QMessageBox::Cancel:\n\t\te->ignore();\n\t\tbreak;\n\t}\n}\n\nvoid ConfigMainWindow::showIntro(void)\n{\n\tstatic const QString str = _(\"Welcome to the qconf graphical configuration tool.\\n\\n\"\n\t\t\"For each option, a blank box indicates the feature is disabled, a check\\n\"\n\t\t\"indicates it is enabled, and a dot indicates that it is to be compiled\\n\"\n\t\t\"as a module.  Clicking on the box will cycle through the three states.\\n\\n\"\n\t\t\"If you do not see an option (e.g., a device driver) that you believe\\n\"\n\t\t\"should be present, try turning on Show All Options under the Options menu.\\n\"\n\t\t\"Although there is no cross reference yet to help you figure out what other\\n\"\n\t\t\"options must be enabled to support the option you are interested in, you can\\n\"\n\t\t\"still view the help of a grayed-out option.\\n\\n\"\n\t\t\"Toggling Show Debug Info under the Options menu will show the dependencies,\\n\"\n\t\t\"which you can then match by examining other options.\\n\\n\");\n\n\tQMessageBox::information(this, \"qconf\", str);\n}\n\nvoid ConfigMainWindow::showAbout(void)\n{\n\tstatic const QString str = _(\"qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\\n\\n\"\n\t\t\"Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\\n\");\n\n\tQMessageBox::information(this, \"qconf\", str);\n}\n\nvoid ConfigMainWindow::saveSettings(void)\n{\n\tconfigSettings->writeEntry(\"/window x\", pos().x());\n\tconfigSettings->writeEntry(\"/window y\", pos().y());\n\tconfigSettings->writeEntry(\"/window width\", size().width());\n\tconfigSettings->writeEntry(\"/window height\", size().height());\n\n\tQString entry;\n\tswitch(configList->mode) {\n\tcase singleMode :\n\t\tentry = \"single\";\n\t\tbreak;\n\n\tcase symbolMode :\n\t\tentry = \"split\";\n\t\tbreak;\n\n\tcase fullMode :\n\t\tentry = \"full\";\n\t\tbreak;\n\n\tdefault:\n\t\tbreak;\n\t}\n\tconfigSettings->writeEntry(\"/listMode\", entry);\n\n\tconfigSettings->writeSizes(\"/split1\", split1->sizes());\n\tconfigSettings->writeSizes(\"/split2\", split2->sizes());\n}\n\nvoid ConfigMainWindow::conf_changed(void)\n{\n\tif (saveAction)\n\t\tsaveAction->setEnabled(conf_get_changed());\n}\n\nvoid fixup_rootmenu(struct menu *menu)\n{\n\tstruct menu *child;\n\tstatic int menu_cnt = 0;\n\n\tmenu->flags |= MENU_ROOT;\n\tfor (child = menu->list; child; child = child->next) {\n\t\tif (child->prompt && child->prompt->type == P_MENU) {\n\t\t\tmenu_cnt++;\n\t\t\tfixup_rootmenu(child);\n\t\t\tmenu_cnt--;\n\t\t} else if (!menu_cnt)\n\t\t\tfixup_rootmenu(child);\n\t}\n}\n\nstatic const char *progname;\n\nstatic void usage(void)\n{\n\tprintf(_(\"%s <config>\\n\"), progname);\n\texit(0);\n}\n\nint main(int ac, char** av)\n{\n\tConfigMainWindow* v;\n\tconst char *name;\n\n\tbindtextdomain(PACKAGE, LOCALEDIR);\n\ttextdomain(PACKAGE);\n\n\tprogname = av[0];\n\tconfigApp = new QApplication(ac, av);\n\tif (ac > 1 && av[1][0] == '-') {\n\t\tswitch (av[1][1]) {\n\t\tcase 'h':\n\t\tcase '?':\n\t\t\tusage();\n\t\t}\n\t\tname = av[2];\n\t} else\n\t\tname = av[1];\n\tif (!name)\n\t\tusage();\n\n\tconf_parse(name);\n\tfixup_rootmenu(&rootmenu);\n\tconf_read(NULL);\n\t//zconfdump(stdout);\n\n\tconfigSettings = new ConfigSettings();\n\tconfigSettings->beginGroup(\"/kconfig/qconf\");\n\tv = new ConfigMainWindow();\n\n\t//zconfdump(stdout);\n\tconfigApp->setMainWidget(v);\n\tconfigApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));\n\tconfigApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));\n\tv->show();\n\tconfigApp->exec();\n\n\tconfigSettings->endGroup();\n\tdelete configSettings;\n\n\treturn 0;\n}\n"
  },
  {
    "path": "kconfig/qconf.h",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#if QT_VERSION < 0x040000\n#include <qlistview.h>\n#else\n#include <q3listview.h>\n#endif\n#include <qsettings.h>\n\n#if QT_VERSION < 0x040000\n#define Q3ValueList             QValueList\n#define Q3PopupMenu             QPopupMenu\n#define Q3ListView              QListView\n#define Q3ListViewItem          QListViewItem\n#define Q3VBox                  QVBox\n#define Q3TextBrowser           QTextBrowser\n#define Q3MainWindow            QMainWindow\n#define Q3Action                QAction\n#define Q3ToolBar               QToolBar\n#define Q3ListViewItemIterator  QListViewItemIterator\n#define Q3FileDialog            QFileDialog\n#endif\n\nclass ConfigView;\nclass ConfigList;\nclass ConfigItem;\nclass ConfigLineEdit;\nclass ConfigMainWindow;\n\nclass ConfigSettings : public QSettings {\npublic:\n\tConfigSettings();\n\tQ3ValueList<int> readSizes(const QString& key, bool *ok);\n\tbool writeSizes(const QString& key, const Q3ValueList<int>& value);\n};\n\nenum colIdx {\n\tpromptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr\n};\nenum listMode {\n\tsingleMode, menuMode, symbolMode, fullMode, listMode\n};\nenum optionMode {\n\tnormalOpt = 0, allOpt, promptOpt\n};\n\nclass ConfigList : public Q3ListView {\n\tQ_OBJECT\n\ttypedef class Q3ListView Parent;\npublic:\n\tConfigList(ConfigView* p, const char *name = 0);\n\tvoid reinit(void);\n\tConfigView* parent(void) const\n\t{\n\t\treturn (ConfigView*)Parent::parent();\n\t}\n\tConfigItem* findConfigItem(struct menu *);\n\nprotected:\n\tvoid keyPressEvent(QKeyEvent *e);\n\tvoid contentsMousePressEvent(QMouseEvent *e);\n\tvoid contentsMouseReleaseEvent(QMouseEvent *e);\n\tvoid contentsMouseMoveEvent(QMouseEvent *e);\n\tvoid contentsMouseDoubleClickEvent(QMouseEvent *e);\n\tvoid focusInEvent(QFocusEvent *e);\n\tvoid contextMenuEvent(QContextMenuEvent *e);\n\npublic slots:\n\tvoid setRootMenu(struct menu *menu);\n\n\tvoid updateList(ConfigItem *item);\n\tvoid setValue(ConfigItem* item, tristate val);\n\tvoid changeValue(ConfigItem* item);\n\tvoid updateSelection(void);\n\tvoid saveSettings(void);\nsignals:\n\tvoid menuChanged(struct menu *menu);\n\tvoid menuSelected(struct menu *menu);\n\tvoid parentSelected(void);\n\tvoid gotFocus(struct menu *);\n\npublic:\n\tvoid updateListAll(void)\n\t{\n\t\tupdateAll = true;\n\t\tupdateList(NULL);\n\t\tupdateAll = false;\n\t}\n\tConfigList* listView()\n\t{\n\t\treturn this;\n\t}\n\tConfigItem* firstChild() const\n\t{\n\t\treturn (ConfigItem *)Parent::firstChild();\n\t}\n\tint mapIdx(colIdx idx)\n\t{\n\t\treturn colMap[idx];\n\t}\n\tvoid addColumn(colIdx idx, const QString& label)\n\t{\n\t\tcolMap[idx] = Parent::addColumn(label);\n\t\tcolRevMap[colMap[idx]] = idx;\n\t}\n\tvoid removeColumn(colIdx idx)\n\t{\n\t\tint col = colMap[idx];\n\t\tif (col >= 0) {\n\t\t\tParent::removeColumn(col);\n\t\t\tcolRevMap[col] = colMap[idx] = -1;\n\t\t}\n\t}\n\tvoid setAllOpen(bool open);\n\tvoid setParentMenu(void);\n\n\tbool menuSkip(struct menu *);\n\n\ttemplate <class P>\n\tvoid updateMenuList(P*, struct menu*);\n\n\tbool updateAll;\n\n\tQPixmap symbolYesPix, symbolModPix, symbolNoPix;\n\tQPixmap choiceYesPix, choiceNoPix;\n\tQPixmap menuPix, menuInvPix, menuBackPix, voidPix;\n\n\tbool showName, showRange, showData;\n\tenum listMode mode;\n\tenum optionMode optMode;\n\tstruct menu *rootEntry;\n\tQColorGroup disabledColorGroup;\n\tQColorGroup inactivedColorGroup;\n\tQ3PopupMenu* headerPopup;\n\nprivate:\n\tint colMap[colNr];\n\tint colRevMap[colNr];\n};\n\nclass ConfigItem : public Q3ListViewItem {\n\ttypedef class Q3ListViewItem Parent;\npublic:\n\tConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)\n\t: Parent(parent, after), menu(m), visible(v), goParent(false)\n\t{\n\t\tinit();\n\t}\n\tConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)\n\t: Parent(parent, after), menu(m), visible(v), goParent(false)\n\t{\n\t\tinit();\n\t}\n\tConfigItem(Q3ListView *parent, ConfigItem *after, bool v)\n\t: Parent(parent, after), menu(0), visible(v), goParent(true)\n\t{\n\t\tinit();\n\t}\n\t~ConfigItem(void);\n\tvoid init(void);\n\tvoid okRename(int col);\n\tvoid updateMenu(void);\n\tvoid testUpdateMenu(bool v);\n\tConfigList* listView() const\n\t{\n\t\treturn (ConfigList*)Parent::listView();\n\t}\n\tConfigItem* firstChild() const\n\t{\n\t\treturn (ConfigItem *)Parent::firstChild();\n\t}\n\tConfigItem* nextSibling() const\n\t{\n\t\treturn (ConfigItem *)Parent::nextSibling();\n\t}\n\tvoid setText(colIdx idx, const QString& text)\n\t{\n\t\tParent::setText(listView()->mapIdx(idx), text);\n\t}\n\tQString text(colIdx idx) const\n\t{\n\t\treturn Parent::text(listView()->mapIdx(idx));\n\t}\n\tvoid setPixmap(colIdx idx, const QPixmap& pm)\n\t{\n\t\tParent::setPixmap(listView()->mapIdx(idx), pm);\n\t}\n\tconst QPixmap* pixmap(colIdx idx) const\n\t{\n\t\treturn Parent::pixmap(listView()->mapIdx(idx));\n\t}\n\tvoid paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);\n\n\tConfigItem* nextItem;\n\tstruct menu *menu;\n\tbool visible;\n\tbool goParent;\n};\n\nclass ConfigLineEdit : public QLineEdit {\n\tQ_OBJECT\n\ttypedef class QLineEdit Parent;\npublic:\n\tConfigLineEdit(ConfigView* parent);\n\tConfigView* parent(void) const\n\t{\n\t\treturn (ConfigView*)Parent::parent();\n\t}\n\tvoid show(ConfigItem *i);\n\tvoid keyPressEvent(QKeyEvent *e);\n\npublic:\n\tConfigItem *item;\n};\n\nclass ConfigView : public Q3VBox {\n\tQ_OBJECT\n\ttypedef class Q3VBox Parent;\npublic:\n\tConfigView(QWidget* parent, const char *name = 0);\n\t~ConfigView(void);\n\tstatic void updateList(ConfigItem* item);\n\tstatic void updateListAll(void);\n\n\tbool showName(void) const { return list->showName; }\n\tbool showRange(void) const { return list->showRange; }\n\tbool showData(void) const { return list->showData; }\npublic slots:\n\tvoid setShowName(bool);\n\tvoid setShowRange(bool);\n\tvoid setShowData(bool);\n\tvoid setOptionMode(QAction *);\nsignals:\n\tvoid showNameChanged(bool);\n\tvoid showRangeChanged(bool);\n\tvoid showDataChanged(bool);\npublic:\n\tConfigList* list;\n\tConfigLineEdit* lineEdit;\n\n\tstatic ConfigView* viewList;\n\tConfigView* nextView;\n\n\tstatic QAction *showNormalAction;\n\tstatic QAction *showAllAction;\n\tstatic QAction *showPromptAction;\n};\n\nclass ConfigInfoView : public Q3TextBrowser {\n\tQ_OBJECT\n\ttypedef class Q3TextBrowser Parent;\npublic:\n\tConfigInfoView(QWidget* parent, const char *name = 0);\n\tbool showDebug(void) const { return _showDebug; }\n\npublic slots:\n\tvoid setInfo(struct menu *menu);\n\tvoid saveSettings(void);\n\tvoid setShowDebug(bool);\n\nsignals:\n\tvoid showDebugChanged(bool);\n\tvoid menuSelected(struct menu *);\n\nprotected:\n\tvoid symbolInfo(void);\n\tvoid menuInfo(void);\n\tQString debug_info(struct symbol *sym);\n\tstatic QString print_filter(const QString &str);\n\tstatic void expr_print_help(void *data, struct symbol *sym, const char *str);\n\tQ3PopupMenu* createPopupMenu(const QPoint& pos);\n\tvoid contentsContextMenuEvent(QContextMenuEvent *e);\n\n\tstruct symbol *sym;\n\tstruct menu *_menu;\n\tbool _showDebug;\n};\n\nclass ConfigSearchWindow : public QDialog {\n\tQ_OBJECT\n\ttypedef class QDialog Parent;\npublic:\n\tConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0);\n\npublic slots:\n\tvoid saveSettings(void);\n\tvoid search(void);\n\nprotected:\n\tQLineEdit* editField;\n\tQPushButton* searchButton;\n\tQSplitter* split;\n\tConfigView* list;\n\tConfigInfoView* info;\n\n\tstruct symbol **result;\n};\n\nclass ConfigMainWindow : public Q3MainWindow {\n\tQ_OBJECT\n\n\tstatic Q3Action *saveAction;\n\tstatic void conf_changed(void);\npublic:\n\tConfigMainWindow(void);\npublic slots:\n\tvoid changeMenu(struct menu *);\n\tvoid setMenuLink(struct menu *);\n\tvoid listFocusChanged(void);\n\tvoid goBack(void);\n\tvoid loadConfig(void);\n\tbool saveConfig(void);\n\tvoid saveConfigAs(void);\n\tvoid searchConfig(void);\n\tvoid showSingleView(void);\n\tvoid showSplitView(void);\n\tvoid showFullView(void);\n\tvoid showIntro(void);\n\tvoid showAbout(void);\n\tvoid saveSettings(void);\n\nprotected:\n\tvoid closeEvent(QCloseEvent *e);\n\n\tConfigSearchWindow *searchWindow;\n\tConfigView *menuView;\n\tConfigList *menuList;\n\tConfigView *configView;\n\tConfigList *configList;\n\tConfigInfoView *helpText;\n\tQ3ToolBar *toolBar;\n\tQ3Action *backAction;\n\tQSplitter* split1;\n\tQSplitter* split2;\n};\n"
  },
  {
    "path": "kconfig/qemu2.cfg",
    "content": "#\n# Automatically generated file; DO NOT EDIT.\n# FROSTED Kernel Configuration\n#\n\n#\n# Platform Selection\n#\nARCH_LM3S=y\n# ARCH_LPC17XX is not set\n# ARCH_STM32F4 is not set\n# ARCH_LPC1763 is not set\n# ARCH_LPC1764 is not set\n# ARCH_LPC1765 is not set\n# ARCH_LPC1766 is not set\n# ARCH_LPC1767 is not set\n# ARCH_LPC1768 is not set\n# ARCH_LPC1769 is not set\nARCH_LM3S6965=y\nFLASH_SIZE_256KB=y\nRAM_SIZE_64KB=y\n# CLK_100MHZ is not set\n# MACH_LPC1768MBED is not set\n# MACH_SEEEDPRO is not set\nMACH_LM3S6965EVB=y\n\n#\n# Kernel Configuration\n#\nKFLASHMEM_SIZE=48\nKRAMMEM_SIZE=6\n\n#\n# Subsystems\n#\n\n#\n# Filesystems\n#\nSYSFS=y\nMEMFS=y\nXIPFS=y\n\n#\n# Sockets\n#\nSOCK_UNIX=y\n\n#\n# Devices\n#\nDEVNULL=y\nDEVUART=y\nUSART_0=y\n# USART_1 is not set\n# USART_2 is not set\n\n#\n# Applications\n#\nFRESH=y\n# TASK2 is not set\n# PRODCONS is not set\n"
  },
  {
    "path": "kconfig/streamline_config.pl",
    "content": "#!/usr/bin/perl -w\n#\n# Copyright 2005-2009 - Steven Rostedt\n# Licensed under the terms of the GNU GPL License version 2\n#\n#  It's simple enough to figure out how this works.\n#  If not, then you can ask me at stripconfig@goodmis.org\n#\n# What it does?\n#\n#   If you have installed a Linux kernel from a distribution\n#   that turns on way too many modules than you need, and\n#   you only want the modules you use, then this program\n#   is perfect for you.\n#\n#   It gives you the ability to turn off all the modules that are\n#   not loaded on your system.\n#\n# Howto:\n#\n#  1. Boot up the kernel that you want to stream line the config on.\n#  2. Change directory to the directory holding the source of the\n#       kernel that you just booted.\n#  3. Copy the configuraton file to this directory as .config\n#  4. Have all your devices that you need modules for connected and\n#      operational (make sure that their corresponding modules are loaded)\n#  5. Run this script redirecting the output to some other file\n#       like config_strip.\n#  6. Back up your old config (if you want too).\n#  7. copy the config_strip file to .config\n#  8. Run \"make oldconfig\"\n#\n#  Now your kernel is ready to be built with only the modules that\n#  are loaded.\n#\n# Here's what I did with my Debian distribution.\n#\n#    cd /usr/src/linux-2.6.10\n#    cp /boot/config-2.6.10-1-686-smp .config\n#    ~/bin/streamline_config > config_strip\n#    mv .config config_sav\n#    mv config_strip .config\n#    make oldconfig\n#\nuse strict;\nuse Getopt::Long;\n\n# set the environment variable LOCALMODCONFIG_DEBUG to get\n# debug output.\nmy $debugprint = 0;\n$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG}));\n\nsub dprint {\n    return if (!$debugprint);\n    print STDERR @_;\n}\n\nmy $config = \".config\";\n\nmy $uname = `uname -r`;\nchomp $uname;\n\nmy @searchconfigs = (\n\t{\n\t    \"file\" => \".config\",\n\t    \"exec\" => \"cat\",\n\t},\n\t{\n\t    \"file\" => \"/proc/config.gz\",\n\t    \"exec\" => \"zcat\",\n\t},\n\t{\n\t    \"file\" => \"/boot/config-$uname\",\n\t    \"exec\" => \"cat\",\n\t},\n\t{\n\t    \"file\" => \"/boot/vmlinuz-$uname\",\n\t    \"exec\" => \"scripts/extract-ikconfig\",\n\t    \"test\" => \"scripts/extract-ikconfig\",\n\t},\n\t{\n\t    \"file\" => \"vmlinux\",\n\t    \"exec\" => \"scripts/extract-ikconfig\",\n\t    \"test\" => \"scripts/extract-ikconfig\",\n\t},\n\t{\n\t    \"file\" => \"/lib/modules/$uname/kernel/kernel/configs.ko\",\n\t    \"exec\" => \"scripts/extract-ikconfig\",\n\t    \"test\" => \"scripts/extract-ikconfig\",\n\t},\n\t{\n\t    \"file\" => \"kernel/configs.ko\",\n\t    \"exec\" => \"scripts/extract-ikconfig\",\n\t    \"test\" => \"scripts/extract-ikconfig\",\n\t},\n\t{\n\t    \"file\" => \"kernel/configs.o\",\n\t    \"exec\" => \"scripts/extract-ikconfig\",\n\t    \"test\" => \"scripts/extract-ikconfig\",\n\t},\n);\n\nsub read_config {\n    foreach my $conf (@searchconfigs) {\n\tmy $file = $conf->{\"file\"};\n\n\tnext if ( ! -f \"$file\");\n\n\tif (defined($conf->{\"test\"})) {\n\t    `$conf->{\"test\"} $conf->{\"file\"} 2>/dev/null`;\n\t    next if ($?);\n\t}\n\n\tmy $exec = $conf->{\"exec\"};\n\n\tprint STDERR \"using config: '$file'\\n\";\n\n\topen(my $infile, '-|', \"$exec $file\") || die \"Failed to run $exec $file\";\n\tmy @x = <$infile>;\n\tclose $infile;\n\treturn @x;\n    }\n    die \"No config file found\";\n}\n\nmy @config_file = read_config;\n\n# Parse options\nmy $localmodconfig = 0;\nmy $localyesconfig = 0;\n\nGetOptions(\"localmodconfig\" => \\$localmodconfig,\n\t   \"localyesconfig\" => \\$localyesconfig);\n\n# Get the build source and top level Kconfig file (passed in)\nmy $ksource = ($ARGV[0] ? $ARGV[0] : '.');\nmy $kconfig = $ARGV[1];\nmy $lsmod_file = $ENV{'LSMOD'};\n\nmy @makefiles = `find $ksource -name Makefile 2>/dev/null`;\nchomp @makefiles;\n\nmy %depends;\nmy %selects;\nmy %prompts;\nmy %objects;\nmy $var;\nmy $iflevel = 0;\nmy @ifdeps;\n\n# prevent recursion\nmy %read_kconfigs;\n\nsub read_kconfig {\n    my ($kconfig) = @_;\n\n    my $state = \"NONE\";\n    my $config;\n\n    my $cont = 0;\n    my $line;\n\n    my $source = \"$ksource/$kconfig\";\n    my $last_source = \"\";\n\n    # Check for any environment variables used\n    while ($source =~ /\\$(\\w+)/ && $last_source ne $source) {\n\tmy $env = $1;\n\t$last_source = $source;\n\t$source =~ s/\\$$env/$ENV{$env}/;\n    }\n\n    open(my $kinfile, '<', $source) || die \"Can't open $kconfig\";\n    while (<$kinfile>) {\n\tchomp;\n\n\t# Make sure that lines ending with \\ continue\n\tif ($cont) {\n\t    $_ = $line . \" \" . $_;\n\t}\n\n\tif (s/\\\\$//) {\n\t    $cont = 1;\n\t    $line = $_;\n\t    next;\n\t}\n\n\t$cont = 0;\n\n\t# collect any Kconfig sources\n\tif (/^source\\s*\"(.*)\"/) {\n\t    my $kconfig = $1;\n\t    # prevent reading twice.\n\t    if (!defined($read_kconfigs{$kconfig})) {\n\t\t$read_kconfigs{$kconfig} = 1;\n\t\tread_kconfig($kconfig);\n\t    }\n\t    next;\n\t}\n\n\t# configs found\n\tif (/^\\s*(menu)?config\\s+(\\S+)\\s*$/) {\n\t    $state = \"NEW\";\n\t    $config = $2;\n\n\t    # Add depends for 'if' nesting\n\t    for (my $i = 0; $i < $iflevel; $i++) {\n\t\tif ($i) {\n\t\t    $depends{$config} .= \" \" . $ifdeps[$i];\n\t\t} else {\n\t\t    $depends{$config} = $ifdeps[$i];\n\t\t}\n\t\t$state = \"DEP\";\n\t    }\n\n\t# collect the depends for the config\n\t} elsif ($state eq \"NEW\" && /^\\s*depends\\s+on\\s+(.*)$/) {\n\t    $state = \"DEP\";\n\t    $depends{$config} = $1;\n\t} elsif ($state eq \"DEP\" && /^\\s*depends\\s+on\\s+(.*)$/) {\n\t    $depends{$config} .= \" \" . $1;\n\t} elsif ($state eq \"DEP\" && /^\\s*def(_(bool|tristate)|ault)\\s+(\\S.*)$/) {\n\t    my $dep = $3;\n\t    if ($dep !~ /^\\s*(y|m|n)\\s*$/) {\n\t\t$dep =~ s/.*\\sif\\s+//;\n\t\t$depends{$config} .= \" \" . $dep;\n\t\tdprint \"Added default depends $dep to $config\\n\";\n\t    }\n\n\t# Get the configs that select this config\n\t} elsif ($state ne \"NONE\" && /^\\s*select\\s+(\\S+)/) {\n\t    my $conf = $1;\n\t    if (defined($selects{$conf})) {\n\t\t$selects{$conf} .= \" \" . $config;\n\t    } else {\n\t\t$selects{$conf} = $config;\n\t    }\n\n\t# configs without prompts must be selected\n\t} elsif ($state ne \"NONE\" && /^\\s*tristate\\s\\S/) {\n\t    # note if the config has a prompt\n\t    $prompts{$config} = 1;\n\n\t# Check for if statements\n\t} elsif (/^if\\s+(.*\\S)\\s*$/) {\n\t    my $deps = $1;\n\t    # remove beginning and ending non text\n\t    $deps =~ s/^[^a-zA-Z0-9_]*//;\n\t    $deps =~ s/[^a-zA-Z0-9_]*$//;\n\n\t    my @deps = split /[^a-zA-Z0-9_]+/, $deps;\n\n\t    $ifdeps[$iflevel++] = join ':', @deps;\n\n\t} elsif (/^endif/) {\n\n\t    $iflevel-- if ($iflevel);\n\n\t# stop on \"help\"\n\t} elsif (/^\\s*help\\s*$/) {\n\t    $state = \"NONE\";\n\t}\n    }\n    close($kinfile);\n}\n\nif ($kconfig) {\n    read_kconfig($kconfig);\n}\n\n# Makefiles can use variables to define their dependencies\nsub convert_vars {\n    my ($line, %vars) = @_;\n\n    my $process = \"\";\n\n    while ($line =~ s/^(.*?)(\\$\\((.*?)\\))//) {\n\tmy $start = $1;\n\tmy $variable = $2;\n\tmy $var = $3;\n\n\tif (defined($vars{$var})) {\n\t    $process .= $start . $vars{$var};\n\t} else {\n\t    $process .= $start . $variable;\n\t}\n    }\n\n    $process .= $line;\n\n    return $process;\n}\n\n# Read all Makefiles to map the configs to the objects\nforeach my $makefile (@makefiles) {\n\n    my $line = \"\";\n    my %make_vars;\n\n    open(my $infile, '<', $makefile) || die \"Can't open $makefile\";\n    while (<$infile>) {\n\t# if this line ends with a backslash, continue\n\tchomp;\n\tif (/^(.*)\\\\$/) {\n\t    $line .= $1;\n\t    next;\n\t}\n\n\t$line .= $_;\n\t$_ = $line;\n\t$line = \"\";\n\n\tmy $objs;\n\n\t# Convert variables in a line (could define configs)\n\t$_ = convert_vars($_, %make_vars);\n\n\t# collect objects after obj-$(CONFIG_FOO_BAR)\n\tif (/obj-\\$\\((CONFIG_[^\\)]*)\\)\\s*[+:]?=\\s*(.*)/) {\n\t    $var = $1;\n\t    $objs = $2;\n\n\t# check if variables are set\n\t} elsif (/^\\s*(\\S+)\\s*[:]?=\\s*(.*\\S)/) {\n\t    $make_vars{$1} = $2;\n\t}\n\tif (defined($objs)) {\n\t    foreach my $obj (split /\\s+/,$objs) {\n\t\t$obj =~ s/-/_/g;\n\t\tif ($obj =~ /(.*)\\.o$/) {\n\t\t    # Objects may be enabled by more than one config.\n\t\t    # Store configs in an array.\n\t\t    my @arr;\n\n\t\t    if (defined($objects{$1})) {\n\t\t\t@arr = @{$objects{$1}};\n\t\t    }\n\n\t\t    $arr[$#arr+1] = $var;\n\n\t\t    # The objects have a hash mapping to a reference\n\t\t    # of an array of configs.\n\t\t    $objects{$1} = \\@arr;\n\t\t}\n\t    }\n\t}\n    }\n    close($infile);\n}\n\nmy %modules;\nmy $linfile;\n\nif (defined($lsmod_file)) {\n    if ( ! -f $lsmod_file) {\n\tif ( -f $ENV{'objtree'}.\"/\".$lsmod_file) {\n\t    $lsmod_file = $ENV{'objtree'}.\"/\".$lsmod_file;\n\t} else {\n\t\tdie \"$lsmod_file not found\";\n\t}\n    }\n\n    my $otype = ( -x $lsmod_file) ? '-|' : '<';\n    open($linfile, $otype, $lsmod_file);\n\n} else {\n\n    # see what modules are loaded on this system\n    my $lsmod;\n\n    foreach my $dir ( (\"/sbin\", \"/bin\", \"/usr/sbin\", \"/usr/bin\") ) {\n\tif ( -x \"$dir/lsmod\" ) {\n\t    $lsmod = \"$dir/lsmod\";\n\t    last;\n\t}\n}\n    if (!defined($lsmod)) {\n\t# try just the path\n\t$lsmod = \"lsmod\";\n    }\n\n    open($linfile, '-|', $lsmod) || die \"Can not call lsmod with $lsmod\";\n}\n\nwhile (<$linfile>) {\n\tnext if (/^Module/);  # Skip the first line.\n\tif (/^(\\S+)/) {\n\t\t$modules{$1} = 1;\n\t}\n}\nclose ($linfile);\n\n# add to the configs hash all configs that are needed to enable\n# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o\n# where we know we need bar.o so we add FOO to the list.\nmy %configs;\nforeach my $module (keys(%modules)) {\n    if (defined($objects{$module})) {\n\tmy @arr = @{$objects{$module}};\n\tforeach my $conf (@arr) {\n\t    $configs{$conf} = $module;\n\t    dprint \"$conf added by direct ($module)\\n\";\n\t    if ($debugprint) {\n\t\tmy $c=$conf;\n\t\t$c =~ s/^CONFIG_//;\n\t\tif (defined($depends{$c})) {\n\t\t    dprint \" deps = $depends{$c}\\n\";\n\t\t} else {\n\t\t    dprint \" no deps\\n\";\n\t\t}\n\t    }\n\t}\n    } else {\n\t# Most likely, someone has a custom (binary?) module loaded.\n\tprint STDERR \"$module config not found!!\\n\";\n    }\n}\n\n# Read the current config, and see what is enabled. We want to\n# ignore configs that we would not enable anyway.\n\nmy %orig_configs;\nmy $valid = \"A-Za-z_0-9\";\n\nforeach my $line (@config_file) {\n    $_ = $line;\n\n    if (/(CONFIG_[$valid]*)=(m|y)/) {\n\t$orig_configs{$1} = $2;\n    }\n}\n\nmy $repeat = 1;\n\nmy $depconfig;\n\n#\n# Note, we do not care about operands (like: &&, ||, !) we want to add any\n# config that is in the depend list of another config. This script does\n# not enable configs that are not already enabled. If we come across a\n# config A that depends on !B, we can still add B to the list of depends\n# to keep on. If A was on in the original config, B would not have been\n# and B would not be turned on by this script.\n#\nsub parse_config_depends\n{\n    my ($p) = @_;\n\n    while ($p =~ /[$valid]/) {\n\n\tif ($p =~ /^[^$valid]*([$valid]+)/) {\n\t    my $conf = \"CONFIG_\" . $1;\n\n\t    $p =~ s/^[^$valid]*[$valid]+//;\n\n\t    # We only need to process if the depend config is a module\n\t    if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq \"m\") {\n\t\tnext;\n\t    }\n\n\t    if (!defined($configs{$conf})) {\n\t\t# We must make sure that this config has its\n\t\t# dependencies met.\n\t\t$repeat = 1; # do again\n\t\tdprint \"$conf selected by depend $depconfig\\n\";\n\t\t$configs{$conf} = 1;\n\t    }\n\t} else {\n\t    die \"this should never happen\";\n\t}\n    }\n}\n\n# Select is treated a bit differently than depends. We call this\n# when a config has no prompt and requires another config to be\n# selected. We use to just select all configs that selected this\n# config, but found that that can balloon into enabling hundreds\n# of configs that we do not care about.\n#\n# The idea is we look at all the configs that select it. If one\n# is already in our list of configs to enable, then there's nothing\n# else to do. If there isn't, we pick the first config that was\n# enabled in the orignal config and use that.\nsub parse_config_selects\n{\n    my ($config, $p) = @_;\n\n    my $next_config;\n\n    while ($p =~ /[$valid]/) {\n\n\tif ($p =~ /^[^$valid]*([$valid]+)/) {\n\t    my $conf = \"CONFIG_\" . $1;\n\n\t    $p =~ s/^[^$valid]*[$valid]+//;\n\n\t    # Make sure that this config exists in the current .config file\n\t    if (!defined($orig_configs{$conf})) {\n\t\tdprint \"$conf not set for $config select\\n\";\n\t\tnext;\n\t    }\n\n\t    # Check if something other than a module selects this config\n\t    if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne \"m\") {\n\t\tdprint \"$conf (non module) selects config, we are good\\n\";\n\t\t# we are good with this\n\t\treturn;\n\t    }\n\t    if (defined($configs{$conf})) {\n\t\tdprint \"$conf selects $config so we are good\\n\";\n\t\t# A set config selects this config, we are good\n\t\treturn;\n\t    }\n\t    # Set this config to be selected\n\t    if (!defined($next_config)) {\n\t\t$next_config = $conf;\n\t    }\n\t} else {\n\t    die \"this should never happen\";\n\t}\n    }\n\n    # If no possible config selected this, then something happened.\n    if (!defined($next_config)) {\n\tprint STDERR \"WARNING: $config is required, but nothing in the\\n\";\n\tprint STDERR \"  current config selects it.\\n\";\n\treturn;\n    }\n\n    # If we are here, then we found no config that is set and\n    # selects this config. Repeat.\n    $repeat = 1;\n    # Make this config need to be selected\n    $configs{$next_config} = 1;\n    dprint \"$next_config selected by select $config\\n\";\n}\n\nmy %process_selects;\n\n# loop through all configs, select their dependencies.\nsub loop_depend {\n    $repeat = 1;\n\n    while ($repeat) {\n\t$repeat = 0;\n\n      forloop:\n\tforeach my $config (keys %configs) {\n\n\t    # If this config is not a module, we do not need to process it\n\t    if (defined($orig_configs{$config}) && $orig_configs{$config} ne \"m\") {\n\t\tnext forloop;\n\t    }\n\n\t    $config =~ s/^CONFIG_//;\n\t    $depconfig = $config;\n\n\t    if (defined($depends{$config})) {\n\t\t# This config has dependencies. Make sure they are also included\n\t\tparse_config_depends $depends{$config};\n\t    }\n\n\t    # If the config has no prompt, then we need to check if a config\n\t    # that is enabled selected it. Or if we need to enable one.\n\t    if (!defined($prompts{$config}) && defined($selects{$config})) {\n\t\t$process_selects{$config} = 1;\n\t    }\n\t}\n    }\n}\n\nsub loop_select {\n\n    foreach my $config (keys %process_selects) {\n\t$config =~ s/^CONFIG_//;\n\n\tdprint \"Process select $config\\n\";\n\n\t# config has no prompt and must be selected.\n\tparse_config_selects $config, $selects{$config};\n    }\n}\n\nwhile ($repeat) {\n    # Get the first set of configs and their dependencies.\n    loop_depend;\n\n    $repeat = 0;\n\n    # Now we need to see if we have to check selects;\n    loop_select;\n}\t    \n\nmy %setconfigs;\n\n# Finally, read the .config file and turn off any module enabled that\n# we could not find a reason to keep enabled.\nforeach my $line (@config_file) {\n    $_ = $line;\n\n    if (/CONFIG_IKCONFIG/) {\n\tif (/# CONFIG_IKCONFIG is not set/) {\n\t    # enable IKCONFIG at least as a module\n\t    print \"CONFIG_IKCONFIG=m\\n\";\n\t    # don't ask about PROC\n\t    print \"# CONFIG_IKCONFIG_PROC is not set\\n\";\n\t} else {\n\t    print;\n\t}\n\tnext;\n    }\n\n    if (/^(CONFIG.*)=(m|y)/) {\n\tif (defined($configs{$1})) {\n\t    if ($localyesconfig) {\n\t        $setconfigs{$1} = 'y';\n\t\tprint \"$1=y\\n\";\n\t\tnext;\n\t    } else {\n\t        $setconfigs{$1} = $2;\n\t    }\n\t} elsif ($2 eq \"m\") {\n\t    print \"# $1 is not set\\n\";\n\t    next;\n\t}\n    }\n    print;\n}\n\n# Integrity check, make sure all modules that we want enabled do\n# indeed have their configs set.\nloop:\nforeach my $module (keys(%modules)) {\n    if (defined($objects{$module})) {\n\tmy @arr = @{$objects{$module}};\n\tforeach my $conf (@arr) {\n\t    if (defined($setconfigs{$conf})) {\n\t\tnext loop;\n\t    }\n\t}\n\tprint STDERR \"module $module did not have configs\";\n\tforeach my $conf (@arr) {\n\t    print STDERR \" \" , $conf;\n\t}\n\tprint STDERR \"\\n\";\n    }\n}\n"
  },
  {
    "path": "kconfig/symbol.c",
    "content": "/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include <regex.h>\n#include <sys/utsname.h>\n\n#include \"lkc.h\"\n\nstruct symbol symbol_yes = {\n\t.name = \"y\",\n\t.curr = { \"y\", yes },\n\t.flags = SYMBOL_CONST|SYMBOL_VALID,\n}, symbol_mod = {\n\t.name = \"m\",\n\t.curr = { \"m\", mod },\n\t.flags = SYMBOL_CONST|SYMBOL_VALID,\n}, symbol_no = {\n\t.name = \"n\",\n\t.curr = { \"n\", no },\n\t.flags = SYMBOL_CONST|SYMBOL_VALID,\n}, symbol_empty = {\n\t.name = \"\",\n\t.curr = { \"\", no },\n\t.flags = SYMBOL_VALID,\n};\n\nstruct symbol *sym_defconfig_list;\nstruct symbol *modules_sym;\ntristate modules_val;\n\nstruct expr *sym_env_list;\n\nstatic void sym_add_default(struct symbol *sym, const char *def)\n{\n\tstruct property *prop = prop_alloc(P_DEFAULT, sym);\n\n\tprop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));\n}\n\nvoid sym_init(void)\n{\n\tstruct symbol *sym;\n\tstruct utsname uts;\n\tstatic bool inited = false;\n\n\tif (inited)\n\t\treturn;\n\tinited = true;\n\n\tuname(&uts);\n\n\tsym = sym_lookup(\"UNAME_RELEASE\", 0);\n\tsym->type = S_STRING;\n\tsym->flags |= SYMBOL_AUTO;\n\tsym_add_default(sym, uts.release);\n}\n\nenum symbol_type sym_get_type(struct symbol *sym)\n{\n\tenum symbol_type type = sym->type;\n\n\tif (type == S_TRISTATE) {\n\t\tif (sym_is_choice_value(sym) && sym->visible == yes)\n\t\t\ttype = S_BOOLEAN;\n\t\telse if (modules_val == no)\n\t\t\ttype = S_BOOLEAN;\n\t}\n\treturn type;\n}\n\nconst char *sym_type_name(enum symbol_type type)\n{\n\tswitch (type) {\n\tcase S_BOOLEAN:\n\t\treturn \"boolean\";\n\tcase S_TRISTATE:\n\t\treturn \"tristate\";\n\tcase S_INT:\n\t\treturn \"integer\";\n\tcase S_HEX:\n\t\treturn \"hex\";\n\tcase S_STRING:\n\t\treturn \"string\";\n\tcase S_UNKNOWN:\n\t\treturn \"unknown\";\n\tcase S_OTHER:\n\t\tbreak;\n\t}\n\treturn \"???\";\n}\n\nstruct property *sym_get_choice_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tfor_all_choices(sym, prop)\n\t\treturn prop;\n\treturn NULL;\n}\n\nstruct property *sym_get_env_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tfor_all_properties(sym, prop, P_ENV)\n\t\treturn prop;\n\treturn NULL;\n}\n\nstruct property *sym_get_default_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tfor_all_defaults(sym, prop) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\tif (prop->visible.tri != no)\n\t\t\treturn prop;\n\t}\n\treturn NULL;\n}\n\nstatic struct property *sym_get_range_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tfor_all_properties(sym, prop, P_RANGE) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\tif (prop->visible.tri != no)\n\t\t\treturn prop;\n\t}\n\treturn NULL;\n}\n\nstatic long long sym_get_range_val(struct symbol *sym, int base)\n{\n\tsym_calc_value(sym);\n\tswitch (sym->type) {\n\tcase S_INT:\n\t\tbase = 10;\n\t\tbreak;\n\tcase S_HEX:\n\t\tbase = 16;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn strtoll(sym->curr.val, NULL, base);\n}\n\nstatic void sym_validate_range(struct symbol *sym)\n{\n\tstruct property *prop;\n\tint base;\n\tlong long val, val2;\n\tchar str[64];\n\n\tswitch (sym->type) {\n\tcase S_INT:\n\t\tbase = 10;\n\t\tbreak;\n\tcase S_HEX:\n\t\tbase = 16;\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\tprop = sym_get_range_prop(sym);\n\tif (!prop)\n\t\treturn;\n\tval = strtoll(sym->curr.val, NULL, base);\n\tval2 = sym_get_range_val(prop->expr->left.sym, base);\n\tif (val >= val2) {\n\t\tval2 = sym_get_range_val(prop->expr->right.sym, base);\n\t\tif (val <= val2)\n\t\t\treturn;\n\t}\n\tif (sym->type == S_INT)\n\t\tsprintf(str, \"%lld\", val2);\n\telse\n\t\tsprintf(str, \"0x%llx\", val2);\n\tsym->curr.val = strdup(str);\n}\n\nstatic void sym_calc_visibility(struct symbol *sym)\n{\n\tstruct property *prop;\n\ttristate tri;\n\n\t/* any prompt visible? */\n\ttri = no;\n\tfor_all_prompts(sym, prop) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\ttri = EXPR_OR(tri, prop->visible.tri);\n\t}\n\tif (tri == mod && (sym->type != S_TRISTATE || modules_val == no))\n\t\ttri = yes;\n\tif (sym->visible != tri) {\n\t\tsym->visible = tri;\n\t\tsym_set_changed(sym);\n\t}\n\tif (sym_is_choice_value(sym))\n\t\treturn;\n\t/* defaulting to \"yes\" if no explicit \"depends on\" are given */\n\ttri = yes;\n\tif (sym->dir_dep.expr)\n\t\ttri = expr_calc_value(sym->dir_dep.expr);\n\tif (tri == mod)\n\t\ttri = yes;\n\tif (sym->dir_dep.tri != tri) {\n\t\tsym->dir_dep.tri = tri;\n\t\tsym_set_changed(sym);\n\t}\n\ttri = no;\n\tif (sym->rev_dep.expr)\n\t\ttri = expr_calc_value(sym->rev_dep.expr);\n\tif (tri == mod && sym_get_type(sym) == S_BOOLEAN)\n\t\ttri = yes;\n\tif (sym->rev_dep.tri != tri) {\n\t\tsym->rev_dep.tri = tri;\n\t\tsym_set_changed(sym);\n\t}\n}\n\n/*\n * Find the default symbol for a choice.\n * First try the default values for the choice symbol\n * Next locate the first visible choice value\n * Return NULL if none was found\n */\nstruct symbol *sym_choice_default(struct symbol *sym)\n{\n\tstruct symbol *def_sym;\n\tstruct property *prop;\n\tstruct expr *e;\n\n\t/* any of the defaults visible? */\n\tfor_all_defaults(sym, prop) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\tif (prop->visible.tri == no)\n\t\t\tcontinue;\n\t\tdef_sym = prop_get_symbol(prop);\n\t\tif (def_sym->visible != no)\n\t\t\treturn def_sym;\n\t}\n\n\t/* just get the first visible value */\n\tprop = sym_get_choice_prop(sym);\n\texpr_list_for_each_sym(prop->expr, e, def_sym)\n\t\tif (def_sym->visible != no)\n\t\t\treturn def_sym;\n\n\t/* failed to locate any defaults */\n\treturn NULL;\n}\n\nstatic struct symbol *sym_calc_choice(struct symbol *sym)\n{\n\tstruct symbol *def_sym;\n\tstruct property *prop;\n\tstruct expr *e;\n\tint flags;\n\n\t/* first calculate all choice values' visibilities */\n\tflags = sym->flags;\n\tprop = sym_get_choice_prop(sym);\n\texpr_list_for_each_sym(prop->expr, e, def_sym) {\n\t\tsym_calc_visibility(def_sym);\n\t\tif (def_sym->visible != no)\n\t\t\tflags &= def_sym->flags;\n\t}\n\n\tsym->flags &= flags | ~SYMBOL_DEF_USER;\n\n\t/* is the user choice visible? */\n\tdef_sym = sym->def[S_DEF_USER].val;\n\tif (def_sym && def_sym->visible != no)\n\t\treturn def_sym;\n\n\tdef_sym = sym_choice_default(sym);\n\n\tif (def_sym == NULL)\n\t\t/* no choice? reset tristate value */\n\t\tsym->curr.tri = no;\n\n\treturn def_sym;\n}\n\nvoid sym_calc_value(struct symbol *sym)\n{\n\tstruct symbol_value newval, oldval;\n\tstruct property *prop;\n\tstruct expr *e;\n\n\tif (!sym)\n\t\treturn;\n\n\tif (sym->flags & SYMBOL_VALID)\n\t\treturn;\n\n\tif (sym_is_choice_value(sym) &&\n\t    sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {\n\t\tsym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;\n\t\tprop = sym_get_choice_prop(sym);\n\t\tsym_calc_value(prop_get_symbol(prop));\n\t}\n\n\tsym->flags |= SYMBOL_VALID;\n\n\toldval = sym->curr;\n\n\tswitch (sym->type) {\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tnewval = symbol_empty.curr;\n\t\tbreak;\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tnewval = symbol_no.curr;\n\t\tbreak;\n\tdefault:\n\t\tsym->curr.val = sym->name;\n\t\tsym->curr.tri = no;\n\t\treturn;\n\t}\n\tif (!sym_is_choice_value(sym))\n\t\tsym->flags &= ~SYMBOL_WRITE;\n\n\tsym_calc_visibility(sym);\n\n\t/* set default if recursively called */\n\tsym->curr = newval;\n\n\tswitch (sym_get_type(sym)) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tif (sym_is_choice_value(sym) && sym->visible == yes) {\n\t\t\tprop = sym_get_choice_prop(sym);\n\t\t\tnewval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;\n\t\t} else {\n\t\t\tif (sym->visible != no) {\n\t\t\t\t/* if the symbol is visible use the user value\n\t\t\t\t * if available, otherwise try the default value\n\t\t\t\t */\n\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\t\tif (sym_has_value(sym)) {\n\t\t\t\t\tnewval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,\n\t\t\t\t\t\t\t      sym->visible);\n\t\t\t\t\tgoto calc_newval;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (sym->rev_dep.tri != no)\n\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\tif (!sym_is_choice(sym)) {\n\t\t\t\tprop = sym_get_default_prop(sym);\n\t\t\t\tif (prop) {\n\t\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\t\t\tnewval.tri = EXPR_AND(expr_calc_value(prop->expr),\n\t\t\t\t\t\t\t      prop->visible.tri);\n\t\t\t\t}\n\t\t\t}\n\t\tcalc_newval:\n\t\t\tif (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {\n\t\t\t\tstruct expr *e;\n\t\t\t\te = expr_simplify_unmet_dep(sym->rev_dep.expr,\n\t\t\t\t    sym->dir_dep.expr);\n\t\t\t\tfprintf(stderr, \"warning: (\");\n\t\t\t\texpr_fprint(e, stderr);\n\t\t\t\tfprintf(stderr, \") selects %s which has unmet direct dependencies (\",\n\t\t\t\t\tsym->name);\n\t\t\t\texpr_fprint(sym->dir_dep.expr, stderr);\n\t\t\t\tfprintf(stderr, \")\\n\");\n\t\t\t\texpr_free(e);\n\t\t\t}\n\t\t\tnewval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);\n\t\t}\n\t\tif (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)\n\t\t\tnewval.tri = yes;\n\t\tbreak;\n\tcase S_STRING:\n\tcase S_HEX:\n\tcase S_INT:\n\t\tif (sym->visible != no) {\n\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\tif (sym_has_value(sym)) {\n\t\t\t\tnewval.val = sym->def[S_DEF_USER].val;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tprop = sym_get_default_prop(sym);\n\t\tif (prop) {\n\t\t\tstruct symbol *ds = prop_get_symbol(prop);\n\t\t\tif (ds) {\n\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\t\tsym_calc_value(ds);\n\t\t\t\tnewval.val = ds->curr.val;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\n\tsym->curr = newval;\n\tif (sym_is_choice(sym) && newval.tri == yes)\n\t\tsym->curr.val = sym_calc_choice(sym);\n\tsym_validate_range(sym);\n\n\tif (memcmp(&oldval, &sym->curr, sizeof(oldval))) {\n\t\tsym_set_changed(sym);\n\t\tif (modules_sym == sym) {\n\t\t\tsym_set_all_changed();\n\t\t\tmodules_val = modules_sym->curr.tri;\n\t\t}\n\t}\n\n\tif (sym_is_choice(sym)) {\n\t\tstruct symbol *choice_sym;\n\n\t\tprop = sym_get_choice_prop(sym);\n\t\texpr_list_for_each_sym(prop->expr, e, choice_sym) {\n\t\t\tif ((sym->flags & SYMBOL_WRITE) &&\n\t\t\t    choice_sym->visible != no)\n\t\t\t\tchoice_sym->flags |= SYMBOL_WRITE;\n\t\t\tif (sym->flags & SYMBOL_CHANGED)\n\t\t\t\tsym_set_changed(choice_sym);\n\t\t}\n\t}\n\n\tif (sym->flags & SYMBOL_AUTO)\n\t\tsym->flags &= ~SYMBOL_WRITE;\n\n\tif (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)\n\t\tset_all_choice_values(sym);\n}\n\nvoid sym_clear_all_valid(void)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tfor_all_symbols(i, sym)\n\t\tsym->flags &= ~SYMBOL_VALID;\n\tsym_add_change_count(1);\n\tif (modules_sym)\n\t\tsym_calc_value(modules_sym);\n}\n\nvoid sym_set_changed(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tsym->flags |= SYMBOL_CHANGED;\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tif (prop->menu)\n\t\t\tprop->menu->flags |= MENU_CHANGED;\n\t}\n}\n\nvoid sym_set_all_changed(void)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tfor_all_symbols(i, sym)\n\t\tsym_set_changed(sym);\n}\n\nbool sym_tristate_within_range(struct symbol *sym, tristate val)\n{\n\tint type = sym_get_type(sym);\n\n\tif (sym->visible == no)\n\t\treturn false;\n\n\tif (type != S_BOOLEAN && type != S_TRISTATE)\n\t\treturn false;\n\n\tif (type == S_BOOLEAN && val == mod)\n\t\treturn false;\n\tif (sym->visible <= sym->rev_dep.tri)\n\t\treturn false;\n\tif (sym_is_choice_value(sym) && sym->visible == yes)\n\t\treturn val == yes;\n\treturn val >= sym->rev_dep.tri && val <= sym->visible;\n}\n\nbool sym_set_tristate_value(struct symbol *sym, tristate val)\n{\n\ttristate oldval = sym_get_tristate_value(sym);\n\n\tif (oldval != val && !sym_tristate_within_range(sym, val))\n\t\treturn false;\n\n\tif (!(sym->flags & SYMBOL_DEF_USER)) {\n\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\tsym_set_changed(sym);\n\t}\n\t/*\n\t * setting a choice value also resets the new flag of the choice\n\t * symbol and all other choice values.\n\t */\n\tif (sym_is_choice_value(sym) && val == yes) {\n\t\tstruct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));\n\t\tstruct property *prop;\n\t\tstruct expr *e;\n\n\t\tcs->def[S_DEF_USER].val = sym;\n\t\tcs->flags |= SYMBOL_DEF_USER;\n\t\tprop = sym_get_choice_prop(cs);\n\t\tfor (e = prop->expr; e; e = e->left.expr) {\n\t\t\tif (e->right.sym->visible != no)\n\t\t\t\te->right.sym->flags |= SYMBOL_DEF_USER;\n\t\t}\n\t}\n\n\tsym->def[S_DEF_USER].tri = val;\n\tif (oldval != val)\n\t\tsym_clear_all_valid();\n\n\treturn true;\n}\n\ntristate sym_toggle_tristate_value(struct symbol *sym)\n{\n\ttristate oldval, newval;\n\n\toldval = newval = sym_get_tristate_value(sym);\n\tdo {\n\t\tswitch (newval) {\n\t\tcase no:\n\t\t\tnewval = mod;\n\t\t\tbreak;\n\t\tcase mod:\n\t\t\tnewval = yes;\n\t\t\tbreak;\n\t\tcase yes:\n\t\t\tnewval = no;\n\t\t\tbreak;\n\t\t}\n\t\tif (sym_set_tristate_value(sym, newval))\n\t\t\tbreak;\n\t} while (oldval != newval);\n\treturn newval;\n}\n\nbool sym_string_valid(struct symbol *sym, const char *str)\n{\n\tsigned char ch;\n\n\tswitch (sym->type) {\n\tcase S_STRING:\n\t\treturn true;\n\tcase S_INT:\n\t\tch = *str++;\n\t\tif (ch == '-')\n\t\t\tch = *str++;\n\t\tif (!isdigit(ch))\n\t\t\treturn false;\n\t\tif (ch == '0' && *str != 0)\n\t\t\treturn false;\n\t\twhile ((ch = *str++)) {\n\t\t\tif (!isdigit(ch))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\tcase S_HEX:\n\t\tif (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))\n\t\t\tstr += 2;\n\t\tch = *str++;\n\t\tdo {\n\t\t\tif (!isxdigit(ch))\n\t\t\t\treturn false;\n\t\t} while ((ch = *str++));\n\t\treturn true;\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (str[0]) {\n\t\tcase 'y': case 'Y':\n\t\tcase 'm': case 'M':\n\t\tcase 'n': case 'N':\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool sym_string_within_range(struct symbol *sym, const char *str)\n{\n\tstruct property *prop;\n\tlong long val;\n\n\tswitch (sym->type) {\n\tcase S_STRING:\n\t\treturn sym_string_valid(sym, str);\n\tcase S_INT:\n\t\tif (!sym_string_valid(sym, str))\n\t\t\treturn false;\n\t\tprop = sym_get_range_prop(sym);\n\t\tif (!prop)\n\t\t\treturn true;\n\t\tval = strtoll(str, NULL, 10);\n\t\treturn val >= sym_get_range_val(prop->expr->left.sym, 10) &&\n\t\t       val <= sym_get_range_val(prop->expr->right.sym, 10);\n\tcase S_HEX:\n\t\tif (!sym_string_valid(sym, str))\n\t\t\treturn false;\n\t\tprop = sym_get_range_prop(sym);\n\t\tif (!prop)\n\t\t\treturn true;\n\t\tval = strtoll(str, NULL, 16);\n\t\treturn val >= sym_get_range_val(prop->expr->left.sym, 16) &&\n\t\t       val <= sym_get_range_val(prop->expr->right.sym, 16);\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (str[0]) {\n\t\tcase 'y': case 'Y':\n\t\t\treturn sym_tristate_within_range(sym, yes);\n\t\tcase 'm': case 'M':\n\t\t\treturn sym_tristate_within_range(sym, mod);\n\t\tcase 'n': case 'N':\n\t\t\treturn sym_tristate_within_range(sym, no);\n\t\t}\n\t\treturn false;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool sym_set_string_value(struct symbol *sym, const char *newval)\n{\n\tconst char *oldval;\n\tchar *val;\n\tint size;\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (newval[0]) {\n\t\tcase 'y': case 'Y':\n\t\t\treturn sym_set_tristate_value(sym, yes);\n\t\tcase 'm': case 'M':\n\t\t\treturn sym_set_tristate_value(sym, mod);\n\t\tcase 'n': case 'N':\n\t\t\treturn sym_set_tristate_value(sym, no);\n\t\t}\n\t\treturn false;\n\tdefault:\n\t\t;\n\t}\n\n\tif (!sym_string_within_range(sym, newval))\n\t\treturn false;\n\n\tif (!(sym->flags & SYMBOL_DEF_USER)) {\n\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\tsym_set_changed(sym);\n\t}\n\n\toldval = sym->def[S_DEF_USER].val;\n\tsize = strlen(newval) + 1;\n\tif (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {\n\t\tsize += 2;\n\t\tsym->def[S_DEF_USER].val = val = xmalloc(size);\n\t\t*val++ = '0';\n\t\t*val++ = 'x';\n\t} else if (!oldval || strcmp(oldval, newval))\n\t\tsym->def[S_DEF_USER].val = val = xmalloc(size);\n\telse\n\t\treturn true;\n\n\tstrcpy(val, newval);\n\tfree((void *)oldval);\n\tsym_clear_all_valid();\n\n\treturn true;\n}\n\n/*\n * Find the default value associated to a symbol.\n * For tristate symbol handle the modules=n case\n * in which case \"m\" becomes \"y\".\n * If the symbol does not have any default then fallback\n * to the fixed default values.\n */\nconst char *sym_get_string_default(struct symbol *sym)\n{\n\tstruct property *prop;\n\tstruct symbol *ds;\n\tconst char *str;\n\ttristate val;\n\n\tsym_calc_visibility(sym);\n\tsym_calc_value(modules_sym);\n\tval = symbol_no.curr.tri;\n\tstr = symbol_empty.curr.val;\n\n\t/* If symbol has a default value look it up */\n\tprop = sym_get_default_prop(sym);\n\tif (prop != NULL) {\n\t\tswitch (sym->type) {\n\t\tcase S_BOOLEAN:\n\t\tcase S_TRISTATE:\n\t\t\t/* The visibility may limit the value from yes => mod */\n\t\t\tval = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t/*\n\t\t\t * The following fails to handle the situation\n\t\t\t * where a default value is further limited by\n\t\t\t * the valid range.\n\t\t\t */\n\t\t\tds = prop_get_symbol(prop);\n\t\t\tif (ds != NULL) {\n\t\t\t\tsym_calc_value(ds);\n\t\t\t\tstr = (const char *)ds->curr.val;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Handle select statements */\n\tval = EXPR_OR(val, sym->rev_dep.tri);\n\n\t/* transpose mod to yes if modules are not enabled */\n\tif (val == mod)\n\t\tif (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)\n\t\t\tval = yes;\n\n\t/* transpose mod to yes if type is bool */\n\tif (sym->type == S_BOOLEAN && val == mod)\n\t\tval = yes;\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (val) {\n\t\tcase no: return \"n\";\n\t\tcase mod: return \"m\";\n\t\tcase yes: return \"y\";\n\t\t}\n\tcase S_INT:\n\tcase S_HEX:\n\t\treturn str;\n\tcase S_STRING:\n\t\treturn str;\n\tcase S_OTHER:\n\tcase S_UNKNOWN:\n\t\tbreak;\n\t}\n\treturn \"\";\n}\n\nconst char *sym_get_string_value(struct symbol *sym)\n{\n\ttristate val;\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tval = sym_get_tristate_value(sym);\n\t\tswitch (val) {\n\t\tcase no:\n\t\t\treturn \"n\";\n\t\tcase mod:\n\t\t\tsym_calc_value(modules_sym);\n\t\t\treturn (modules_sym->curr.tri == no) ? \"n\" : \"m\";\n\t\tcase yes:\n\t\t\treturn \"y\";\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn (const char *)sym->curr.val;\n}\n\nbool sym_is_changable(struct symbol *sym)\n{\n\treturn sym->visible > sym->rev_dep.tri;\n}\n\nstatic unsigned strhash(const char *s)\n{\n\t/* fnv32 hash */\n\tunsigned hash = 2166136261U;\n\tfor (; *s; s++)\n\t\thash = (hash ^ *s) * 0x01000193;\n\treturn hash;\n}\n\nstruct symbol *sym_lookup(const char *name, int flags)\n{\n\tstruct symbol *symbol;\n\tchar *new_name;\n\tint hash;\n\n\tif (name) {\n\t\tif (name[0] && !name[1]) {\n\t\t\tswitch (name[0]) {\n\t\t\tcase 'y': return &symbol_yes;\n\t\t\tcase 'm': return &symbol_mod;\n\t\t\tcase 'n': return &symbol_no;\n\t\t\t}\n\t\t}\n\t\thash = strhash(name) % SYMBOL_HASHSIZE;\n\n\t\tfor (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {\n\t\t\tif (symbol->name &&\n\t\t\t    !strcmp(symbol->name, name) &&\n\t\t\t    (flags ? symbol->flags & flags\n\t\t\t\t   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))\n\t\t\t\treturn symbol;\n\t\t}\n\t\tnew_name = strdup(name);\n\t} else {\n\t\tnew_name = NULL;\n\t\thash = 0;\n\t}\n\n\tsymbol = xmalloc(sizeof(*symbol));\n\tmemset(symbol, 0, sizeof(*symbol));\n\tsymbol->name = new_name;\n\tsymbol->type = S_UNKNOWN;\n\tsymbol->flags |= flags;\n\n\tsymbol->next = symbol_hash[hash];\n\tsymbol_hash[hash] = symbol;\n\n\treturn symbol;\n}\n\nstruct symbol *sym_find(const char *name)\n{\n\tstruct symbol *symbol = NULL;\n\tint hash = 0;\n\n\tif (!name)\n\t\treturn NULL;\n\n\tif (name[0] && !name[1]) {\n\t\tswitch (name[0]) {\n\t\tcase 'y': return &symbol_yes;\n\t\tcase 'm': return &symbol_mod;\n\t\tcase 'n': return &symbol_no;\n\t\t}\n\t}\n\thash = strhash(name) % SYMBOL_HASHSIZE;\n\n\tfor (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {\n\t\tif (symbol->name &&\n\t\t    !strcmp(symbol->name, name) &&\n\t\t    !(symbol->flags & SYMBOL_CONST))\n\t\t\t\tbreak;\n\t}\n\n\treturn symbol;\n}\n\n/*\n * Expand symbol's names embedded in the string given in argument. Symbols'\n * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to\n * the empty string.\n */\nconst char *sym_expand_string_value(const char *in)\n{\n\tconst char *src;\n\tchar *res;\n\tsize_t reslen;\n\n\treslen = strlen(in) + 1;\n\tres = xmalloc(reslen);\n\tres[0] = '\\0';\n\n\twhile ((src = strchr(in, '$'))) {\n\t\tchar *p, name[SYMBOL_MAXLENGTH];\n\t\tconst char *symval = \"\";\n\t\tstruct symbol *sym;\n\t\tsize_t newlen;\n\n\t\tstrncat(res, in, src - in);\n\t\tsrc++;\n\n\t\tp = name;\n\t\twhile (isalnum(*src) || *src == '_')\n\t\t\t*p++ = *src++;\n\t\t*p = '\\0';\n\n\t\tsym = sym_find(name);\n\t\tif (sym != NULL) {\n\t\t\tsym_calc_value(sym);\n\t\t\tsymval = sym_get_string_value(sym);\n\t\t}\n\n\t\tnewlen = strlen(res) + strlen(symval) + strlen(src) + 1;\n\t\tif (newlen > reslen) {\n\t\t\treslen = newlen;\n\t\t\tres = realloc(res, reslen);\n\t\t}\n\n\t\tstrcat(res, symval);\n\t\tin = src;\n\t}\n\tstrcat(res, in);\n\n\treturn res;\n}\n\nconst char *sym_escape_string_value(const char *in)\n{\n\tconst char *p;\n\tsize_t reslen;\n\tchar *res;\n\tsize_t l;\n\n\treslen = strlen(in) + strlen(\"\\\"\\\"\") + 1;\n\n\tp = in;\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\\"\\\\\");\n\t\tp += l;\n\n\t\tif (p[0] == '\\0')\n\t\t\tbreak;\n\n\t\treslen++;\n\t\tp++;\n\t}\n\n\tres = xmalloc(reslen);\n\tres[0] = '\\0';\n\n\tstrcat(res, \"\\\"\");\n\n\tp = in;\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\\"\\\\\");\n\t\tstrncat(res, p, l);\n\t\tp += l;\n\n\t\tif (p[0] == '\\0')\n\t\t\tbreak;\n\n\t\tstrcat(res, \"\\\\\");\n\t\tstrncat(res, p++, 1);\n\t}\n\n\tstrcat(res, \"\\\"\");\n\treturn res;\n}\n\nstruct sym_match {\n\tstruct symbol\t*sym;\n\toff_t\t\tso, eo;\n};\n\n/* Compare matched symbols as thus:\n * - first, symbols that match exactly\n * - then, alphabetical sort\n */\nstatic int sym_rel_comp(const void *sym1, const void *sym2)\n{\n\tconst struct sym_match *s1 = sym1;\n\tconst struct sym_match *s2 = sym2;\n\tint exact1, exact2;\n\n\t/* Exact match:\n\t * - if matched length on symbol s1 is the length of that symbol,\n\t *   then this symbol should come first;\n\t * - if matched length on symbol s2 is the length of that symbol,\n\t *   then this symbol should come first.\n\t * Note: since the search can be a regexp, both symbols may match\n\t * exactly; if this is the case, we can't decide which comes first,\n\t * and we fallback to sorting alphabetically.\n\t */\n\texact1 = (s1->eo - s1->so) == strlen(s1->sym->name);\n\texact2 = (s2->eo - s2->so) == strlen(s2->sym->name);\n\tif (exact1 && !exact2)\n\t\treturn -1;\n\tif (!exact1 && exact2)\n\t\treturn 1;\n\n\t/* As a fallback, sort symbols alphabetically */\n\treturn strcmp(s1->sym->name, s2->sym->name);\n}\n\nstruct symbol **sym_re_search(const char *pattern)\n{\n\tstruct symbol *sym, **sym_arr = NULL;\n\tstruct sym_match *sym_match_arr = NULL;\n\tint i, cnt, size;\n\tregex_t re;\n\tregmatch_t match[1];\n\n\tcnt = size = 0;\n\t/* Skip if empty */\n\tif (strlen(pattern) == 0)\n\t\treturn NULL;\n\tif (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))\n\t\treturn NULL;\n\n\tfor_all_symbols(i, sym) {\n\t\tif (sym->flags & SYMBOL_CONST || !sym->name)\n\t\t\tcontinue;\n\t\tif (regexec(&re, sym->name, 1, match, 0))\n\t\t\tcontinue;\n\t\tif (cnt >= size) {\n\t\t\tvoid *tmp;\n\t\t\tsize += 16;\n\t\t\ttmp = realloc(sym_match_arr, size * sizeof(struct sym_match));\n\t\t\tif (!tmp)\n\t\t\t\tgoto sym_re_search_free;\n\t\t\tsym_match_arr = tmp;\n\t\t}\n\t\tsym_calc_value(sym);\n\t\t/* As regexec returned 0, we know we have a match, so\n\t\t * we can use match[0].rm_[se]o without further checks\n\t\t */\n\t\tsym_match_arr[cnt].so = match[0].rm_so;\n\t\tsym_match_arr[cnt].eo = match[0].rm_eo;\n\t\tsym_match_arr[cnt++].sym = sym;\n\t}\n\tif (sym_match_arr) {\n\t\tqsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);\n\t\tsym_arr = malloc((cnt+1) * sizeof(struct symbol));\n\t\tif (!sym_arr)\n\t\t\tgoto sym_re_search_free;\n\t\tfor (i = 0; i < cnt; i++)\n\t\t\tsym_arr[i] = sym_match_arr[i].sym;\n\t\tsym_arr[cnt] = NULL;\n\t}\nsym_re_search_free:\n\t/* sym_match_arr can be NULL if no match, but free(NULL) is OK */\n\tfree(sym_match_arr);\n\tregfree(&re);\n\n\treturn sym_arr;\n}\n\n/*\n * When we check for recursive dependencies we use a stack to save\n * current state so we can print out relevant info to user.\n * The entries are located on the call stack so no need to free memory.\n * Note insert() remove() must always match to properly clear the stack.\n */\nstatic struct dep_stack {\n\tstruct dep_stack *prev, *next;\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct expr *expr;\n} *check_top;\n\nstatic void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)\n{\n\tmemset(stack, 0, sizeof(*stack));\n\tif (check_top)\n\t\tcheck_top->next = stack;\n\tstack->prev = check_top;\n\tstack->sym = sym;\n\tcheck_top = stack;\n}\n\nstatic void dep_stack_remove(void)\n{\n\tcheck_top = check_top->prev;\n\tif (check_top)\n\t\tcheck_top->next = NULL;\n}\n\n/*\n * Called when we have detected a recursive dependency.\n * check_top point to the top of the stact so we use\n * the ->prev pointer to locate the bottom of the stack.\n */\nstatic void sym_check_print_recursive(struct symbol *last_sym)\n{\n\tstruct dep_stack *stack;\n\tstruct symbol *sym, *next_sym;\n\tstruct menu *menu = NULL;\n\tstruct property *prop;\n\tstruct dep_stack cv_stack;\n\n\tif (sym_is_choice_value(last_sym)) {\n\t\tdep_stack_insert(&cv_stack, last_sym);\n\t\tlast_sym = prop_get_symbol(sym_get_choice_prop(last_sym));\n\t}\n\n\tfor (stack = check_top; stack != NULL; stack = stack->prev)\n\t\tif (stack->sym == last_sym)\n\t\t\tbreak;\n\tif (!stack) {\n\t\tfprintf(stderr, \"unexpected recursive dependency error\\n\");\n\t\treturn;\n\t}\n\n\tfor (; stack; stack = stack->next) {\n\t\tsym = stack->sym;\n\t\tnext_sym = stack->next ? stack->next->sym : last_sym;\n\t\tprop = stack->prop;\n\t\tif (prop == NULL)\n\t\t\tprop = stack->sym->prop;\n\n\t\t/* for choice values find the menu entry (used below) */\n\t\tif (sym_is_choice(sym) || sym_is_choice_value(sym)) {\n\t\t\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\t\t\tmenu = prop->menu;\n\t\t\t\tif (prop->menu)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (stack->sym == last_sym)\n\t\t\tfprintf(stderr, \"%s:%d:error: recursive dependency detected!\\n\",\n\t\t\t\tprop->file->name, prop->lineno);\n\t\tif (stack->expr) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s %s value contains %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tprop_get_type_name(prop->type),\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (stack->prop) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s depends on %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (sym_is_choice(sym)) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tchoice %s contains symbol %s\\n\",\n\t\t\t\tmenu->file->name, menu->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (sym_is_choice_value(sym)) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s is part of choice %s\\n\",\n\t\t\t\tmenu->file->name, menu->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s is selected by %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t}\n\t}\n\n\tif (check_top == &cv_stack)\n\t\tdep_stack_remove();\n}\n\nstatic struct symbol *sym_check_expr_deps(struct expr *e)\n{\n\tstruct symbol *sym;\n\n\tif (!e)\n\t\treturn NULL;\n\tswitch (e->type) {\n\tcase E_OR:\n\tcase E_AND:\n\t\tsym = sym_check_expr_deps(e->left.expr);\n\t\tif (sym)\n\t\t\treturn sym;\n\t\treturn sym_check_expr_deps(e->right.expr);\n\tcase E_NOT:\n\t\treturn sym_check_expr_deps(e->left.expr);\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\t\tsym = sym_check_deps(e->left.sym);\n\t\tif (sym)\n\t\t\treturn sym;\n\t\treturn sym_check_deps(e->right.sym);\n\tcase E_SYMBOL:\n\t\treturn sym_check_deps(e->left.sym);\n\tdefault:\n\t\tbreak;\n\t}\n\tprintf(\"Oops! How to check %d?\\n\", e->type);\n\treturn NULL;\n}\n\n/* return NULL when dependencies are OK */\nstatic struct symbol *sym_check_sym_deps(struct symbol *sym)\n{\n\tstruct symbol *sym2;\n\tstruct property *prop;\n\tstruct dep_stack stack;\n\n\tdep_stack_insert(&stack, sym);\n\n\tsym2 = sym_check_expr_deps(sym->rev_dep.expr);\n\tif (sym2)\n\t\tgoto out;\n\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tif (prop->type == P_CHOICE || prop->type == P_SELECT)\n\t\t\tcontinue;\n\t\tstack.prop = prop;\n\t\tsym2 = sym_check_expr_deps(prop->visible.expr);\n\t\tif (sym2)\n\t\t\tbreak;\n\t\tif (prop->type != P_DEFAULT || sym_is_choice(sym))\n\t\t\tcontinue;\n\t\tstack.expr = prop->expr;\n\t\tsym2 = sym_check_expr_deps(prop->expr);\n\t\tif (sym2)\n\t\t\tbreak;\n\t\tstack.expr = NULL;\n\t}\n\nout:\n\tdep_stack_remove();\n\n\treturn sym2;\n}\n\nstatic struct symbol *sym_check_choice_deps(struct symbol *choice)\n{\n\tstruct symbol *sym, *sym2;\n\tstruct property *prop;\n\tstruct expr *e;\n\tstruct dep_stack stack;\n\n\tdep_stack_insert(&stack, choice);\n\n\tprop = sym_get_choice_prop(choice);\n\texpr_list_for_each_sym(prop->expr, e, sym)\n\t\tsym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);\n\n\tchoice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);\n\tsym2 = sym_check_sym_deps(choice);\n\tchoice->flags &= ~SYMBOL_CHECK;\n\tif (sym2)\n\t\tgoto out;\n\n\texpr_list_for_each_sym(prop->expr, e, sym) {\n\t\tsym2 = sym_check_sym_deps(sym);\n\t\tif (sym2)\n\t\t\tbreak;\n\t}\nout:\n\texpr_list_for_each_sym(prop->expr, e, sym)\n\t\tsym->flags &= ~SYMBOL_CHECK;\n\n\tif (sym2 && sym_is_choice_value(sym2) &&\n\t    prop_get_symbol(sym_get_choice_prop(sym2)) == choice)\n\t\tsym2 = choice;\n\n\tdep_stack_remove();\n\n\treturn sym2;\n}\n\nstruct symbol *sym_check_deps(struct symbol *sym)\n{\n\tstruct symbol *sym2;\n\tstruct property *prop;\n\n\tif (sym->flags & SYMBOL_CHECK) {\n\t\tsym_check_print_recursive(sym);\n\t\treturn sym;\n\t}\n\tif (sym->flags & SYMBOL_CHECKED)\n\t\treturn NULL;\n\n\tif (sym_is_choice_value(sym)) {\n\t\tstruct dep_stack stack;\n\n\t\t/* for choice groups start the check with main choice symbol */\n\t\tdep_stack_insert(&stack, sym);\n\t\tprop = sym_get_choice_prop(sym);\n\t\tsym2 = sym_check_deps(prop_get_symbol(prop));\n\t\tdep_stack_remove();\n\t} else if (sym_is_choice(sym)) {\n\t\tsym2 = sym_check_choice_deps(sym);\n\t} else {\n\t\tsym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);\n\t\tsym2 = sym_check_sym_deps(sym);\n\t\tsym->flags &= ~SYMBOL_CHECK;\n\t}\n\n\tif (sym2 && sym2 == sym)\n\t\tsym2 = NULL;\n\n\treturn sym2;\n}\n\nstruct property *prop_alloc(enum prop_type type, struct symbol *sym)\n{\n\tstruct property *prop;\n\tstruct property **propp;\n\n\tprop = xmalloc(sizeof(*prop));\n\tmemset(prop, 0, sizeof(*prop));\n\tprop->type = type;\n\tprop->sym = sym;\n\tprop->file = current_file;\n\tprop->lineno = zconf_lineno();\n\n\t/* append property to the prop list of symbol */\n\tif (sym) {\n\t\tfor (propp = &sym->prop; *propp; propp = &(*propp)->next)\n\t\t\t;\n\t\t*propp = prop;\n\t}\n\n\treturn prop;\n}\n\nstruct symbol *prop_get_symbol(struct property *prop)\n{\n\tif (prop->expr && (prop->expr->type == E_SYMBOL ||\n\t\t\t   prop->expr->type == E_LIST))\n\t\treturn prop->expr->left.sym;\n\treturn NULL;\n}\n\nconst char *prop_get_type_name(enum prop_type type)\n{\n\tswitch (type) {\n\tcase P_PROMPT:\n\t\treturn \"prompt\";\n\tcase P_ENV:\n\t\treturn \"env\";\n\tcase P_COMMENT:\n\t\treturn \"comment\";\n\tcase P_MENU:\n\t\treturn \"menu\";\n\tcase P_DEFAULT:\n\t\treturn \"default\";\n\tcase P_CHOICE:\n\t\treturn \"choice\";\n\tcase P_SELECT:\n\t\treturn \"select\";\n\tcase P_RANGE:\n\t\treturn \"range\";\n\tcase P_SYMBOL:\n\t\treturn \"symbol\";\n\tcase P_UNKNOWN:\n\t\tbreak;\n\t}\n\treturn \"unknown\";\n}\n\nstatic void prop_add_env(const char *env)\n{\n\tstruct symbol *sym, *sym2;\n\tstruct property *prop;\n\tchar *p;\n\n\tsym = current_entry->sym;\n\tsym->flags |= SYMBOL_AUTO;\n\tfor_all_properties(sym, prop, P_ENV) {\n\t\tsym2 = prop_get_symbol(prop);\n\t\tif (strcmp(sym2->name, env))\n\t\t\tmenu_warn(current_entry, \"redefining environment symbol from %s\",\n\t\t\t\t  sym2->name);\n\t\treturn;\n\t}\n\n\tprop = prop_alloc(P_ENV, sym);\n\tprop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));\n\n\tsym_env_list = expr_alloc_one(E_LIST, sym_env_list);\n\tsym_env_list->right.sym = sym;\n\n\tp = getenv(env);\n\tif (p)\n\t\tsym_add_default(sym, p);\n\telse\n\t\tmenu_warn(current_entry, \"environment variable %s undefined\", env);\n}\n"
  },
  {
    "path": "kconfig/util.c",
    "content": "/*\n * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>\n * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>\n *\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"lkc.h\"\n\n/* file already present in list? If not add it */\nstruct file *file_lookup(const char *name)\n{\n\tstruct file *file;\n\tconst char *file_name = sym_expand_string_value(name);\n\n\tfor (file = file_list; file; file = file->next) {\n\t\tif (!strcmp(name, file->name)) {\n\t\t\tfree((void *)file_name);\n\t\t\treturn file;\n\t\t}\n\t}\n\n\tfile = xmalloc(sizeof(*file));\n\tmemset(file, 0, sizeof(*file));\n\tfile->name = file_name;\n\tfile->next = file_list;\n\tfile_list = file;\n\treturn file;\n}\n\n/* write a dependency file as used by kbuild to track dependencies */\nint file_write_dep(const char *name)\n{\n\tstruct symbol *sym, *env_sym;\n\tstruct expr *e;\n\tstruct file *file;\n\tFILE *out;\n\n\tif (!name)\n\t\tname = \".kconfig.d\";\n\tout = fopen(\"..config.tmp\", \"w\");\n\tif (!out)\n\t\treturn 1;\n\tfprintf(out, \"deps_config := \\\\\\n\");\n\tfor (file = file_list; file; file = file->next) {\n\t\tif (file->next)\n\t\t\tfprintf(out, \"\\t%s \\\\\\n\", file->name);\n\t\telse\n\t\t\tfprintf(out, \"\\t%s\\n\", file->name);\n\t}\n\tfprintf(out, \"\\n%s: \\\\\\n\"\n\t\t     \"\\t$(deps_config)\\n\\n\", conf_get_autoconfig_name());\n\n\texpr_list_for_each_sym(sym_env_list, e, sym) {\n\t\tstruct property *prop;\n\t\tconst char *value;\n\n\t\tprop = sym_get_env_prop(sym);\n\t\tenv_sym = prop_get_symbol(prop);\n\t\tif (!env_sym)\n\t\t\tcontinue;\n\t\tvalue = getenv(env_sym->name);\n\t\tif (!value)\n\t\t\tvalue = \"\";\n\t\tfprintf(out, \"ifneq \\\"$(%s)\\\" \\\"%s\\\"\\n\", env_sym->name, value);\n\t\tfprintf(out, \"%s: FORCE\\n\", conf_get_autoconfig_name());\n\t\tfprintf(out, \"endif\\n\");\n\t}\n\n\tfprintf(out, \"\\n$(deps_config): ;\\n\");\n\tfclose(out);\n\trename(\"..config.tmp\", name);\n\treturn 0;\n}\n\n\n/* Allocate initial growable string */\nstruct gstr str_new(void)\n{\n\tstruct gstr gs;\n\tgs.s = xmalloc(sizeof(char) * 64);\n\tgs.len = 64;\n\tgs.max_width = 0;\n\tstrcpy(gs.s, \"\\0\");\n\treturn gs;\n}\n\n/* Allocate and assign growable string */\nstruct gstr str_assign(const char *s)\n{\n\tstruct gstr gs;\n\tgs.s = strdup(s);\n\tgs.len = strlen(s) + 1;\n\tgs.max_width = 0;\n\treturn gs;\n}\n\n/* Free storage for growable string */\nvoid str_free(struct gstr *gs)\n{\n\tif (gs->s)\n\t\tfree(gs->s);\n\tgs->s = NULL;\n\tgs->len = 0;\n}\n\n/* Append to growable string */\nvoid str_append(struct gstr *gs, const char *s)\n{\n\tsize_t l;\n\tif (s) {\n\t\tl = strlen(gs->s) + strlen(s) + 1;\n\t\tif (l > gs->len) {\n\t\t\tgs->s   = realloc(gs->s, l);\n\t\t\tgs->len = l;\n\t\t}\n\t\tstrcat(gs->s, s);\n\t}\n}\n\n/* Append printf formatted string to growable string */\nvoid str_printf(struct gstr *gs, const char *fmt, ...)\n{\n\tva_list ap;\n\tchar s[10000]; /* big enough... */\n\tva_start(ap, fmt);\n\tvsnprintf(s, sizeof(s), fmt, ap);\n\tstr_append(gs, s);\n\tva_end(ap);\n}\n\n/* Retrieve value of growable string */\nconst char *str_get(struct gstr *gs)\n{\n\treturn gs->s;\n}\n\nvoid *xmalloc(size_t size)\n{\n\tvoid *p = malloc(size);\n\tif (p)\n\t\treturn p;\n\tfprintf(stderr, \"Out of memory.\\n\");\n\texit(1);\n}\n\nvoid *xcalloc(size_t nmemb, size_t size)\n{\n\tvoid *p = calloc(nmemb, size);\n\tif (p)\n\t\treturn p;\n\tfprintf(stderr, \"Out of memory.\\n\");\n\texit(1);\n}\n\n\n"
  },
  {
    "path": "kconfig/zconf.gperf",
    "content": "%language=ANSI-C\n%define hash-function-name kconf_id_hash\n%define lookup-function-name kconf_id_lookup\n%define string-pool-name kconf_id_strings\n%compare-strncmp\n%enum\n%pic\n%struct-type\n\nstruct kconf_id;\n\nstatic const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);\n\n%%\nmainmenu,\tT_MAINMENU,\tTF_COMMAND\nmenu,\t\tT_MENU,\t\tTF_COMMAND\nendmenu,\tT_ENDMENU,\tTF_COMMAND\nsource,\t\tT_SOURCE,\tTF_COMMAND\nchoice,\t\tT_CHOICE,\tTF_COMMAND\nendchoice,\tT_ENDCHOICE,\tTF_COMMAND\ncomment,\tT_COMMENT,\tTF_COMMAND\nconfig,\t\tT_CONFIG,\tTF_COMMAND\nmenuconfig,\tT_MENUCONFIG,\tTF_COMMAND\nhelp,\t\tT_HELP,\t\tTF_COMMAND\nif,\t\tT_IF,\t\tTF_COMMAND|TF_PARAM\nendif,\t\tT_ENDIF,\tTF_COMMAND\ndepends,\tT_DEPENDS,\tTF_COMMAND\noptional,\tT_OPTIONAL,\tTF_COMMAND\ndefault,\tT_DEFAULT,\tTF_COMMAND, S_UNKNOWN\nprompt,\t\tT_PROMPT,\tTF_COMMAND\ntristate,\tT_TYPE,\t\tTF_COMMAND, S_TRISTATE\ndef_tristate,\tT_DEFAULT,\tTF_COMMAND, S_TRISTATE\nbool,\t\tT_TYPE,\t\tTF_COMMAND, S_BOOLEAN\nboolean,\tT_TYPE,\t\tTF_COMMAND, S_BOOLEAN\ndef_bool,\tT_DEFAULT,\tTF_COMMAND, S_BOOLEAN\nint,\t\tT_TYPE,\t\tTF_COMMAND, S_INT\nhex,\t\tT_TYPE,\t\tTF_COMMAND, S_HEX\nstring,\t\tT_TYPE,\t\tTF_COMMAND, S_STRING\nselect,\t\tT_SELECT,\tTF_COMMAND\nrange,\t\tT_RANGE,\tTF_COMMAND\nvisible,\tT_VISIBLE,\tTF_COMMAND\noption,\t\tT_OPTION,\tTF_COMMAND\non,\t\tT_ON,\t\tTF_PARAM\nmodules,\tT_OPT_MODULES,\tTF_OPTION\ndefconfig_list,\tT_OPT_DEFCONFIG_LIST,TF_OPTION\nenv,\t\tT_OPT_ENV,\tTF_OPTION\nallnoconfig_y,\tT_OPT_ALLNOCONFIG_Y,TF_OPTION\n%%\n"
  },
  {
    "path": "kconfig/zconf.hash.c_shipped",
    "content": "/* ANSI-C code produced by gperf version 3.0.4 */\n/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf  */\n\n#if !((' ' == 32) && ('!' == 33) && ('\"' == 34) && ('#' == 35) \\\n      && ('%' == 37) && ('&' == 38) && ('\\'' == 39) && ('(' == 40) \\\n      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \\\n      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \\\n      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \\\n      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \\\n      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \\\n      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \\\n      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \\\n      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \\\n      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \\\n      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \\\n      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \\\n      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \\\n      && ('Z' == 90) && ('[' == 91) && ('\\\\' == 92) && (']' == 93) \\\n      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \\\n      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \\\n      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \\\n      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \\\n      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \\\n      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \\\n      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \\\n      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))\n/* The character set is not based on ISO-646.  */\n#error \"gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>.\"\n#endif\n\n#line 10 \"scripts/kconfig/zconf.gperf\"\nstruct kconf_id;\n\nstatic const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);\n/* maximum key range = 71, duplicates = 0 */\n\n#ifdef __GNUC__\n__inline\n#else\n#ifdef __cplusplus\ninline\n#endif\n#endif\nstatic unsigned int\nkconf_id_hash (register const char *str, register unsigned int len)\n{\n  static const unsigned char asso_values[] =\n    {\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73,  5, 25, 25,\n       0,  0,  0,  5,  0,  0, 73, 73,  5,  0,\n      10,  5, 45, 73, 20, 20,  0, 15, 15, 73,\n      20,  5, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\n      73, 73, 73, 73, 73, 73\n    };\n  register int hval = len;\n\n  switch (hval)\n    {\n      default:\n        hval += asso_values[(unsigned char)str[2]];\n      /*FALLTHROUGH*/\n      case 2:\n      case 1:\n        hval += asso_values[(unsigned char)str[0]];\n        break;\n    }\n  return hval + asso_values[(unsigned char)str[len - 1]];\n}\n\nstruct kconf_id_strings_t\n  {\n    char kconf_id_strings_str2[sizeof(\"if\")];\n    char kconf_id_strings_str3[sizeof(\"int\")];\n    char kconf_id_strings_str5[sizeof(\"endif\")];\n    char kconf_id_strings_str7[sizeof(\"default\")];\n    char kconf_id_strings_str8[sizeof(\"tristate\")];\n    char kconf_id_strings_str9[sizeof(\"endchoice\")];\n    char kconf_id_strings_str12[sizeof(\"def_tristate\")];\n    char kconf_id_strings_str13[sizeof(\"def_bool\")];\n    char kconf_id_strings_str14[sizeof(\"defconfig_list\")];\n    char kconf_id_strings_str17[sizeof(\"on\")];\n    char kconf_id_strings_str18[sizeof(\"optional\")];\n    char kconf_id_strings_str21[sizeof(\"option\")];\n    char kconf_id_strings_str22[sizeof(\"endmenu\")];\n    char kconf_id_strings_str23[sizeof(\"mainmenu\")];\n    char kconf_id_strings_str25[sizeof(\"menuconfig\")];\n    char kconf_id_strings_str27[sizeof(\"modules\")];\n    char kconf_id_strings_str28[sizeof(\"allnoconfig_y\")];\n    char kconf_id_strings_str29[sizeof(\"menu\")];\n    char kconf_id_strings_str31[sizeof(\"select\")];\n    char kconf_id_strings_str32[sizeof(\"comment\")];\n    char kconf_id_strings_str33[sizeof(\"env\")];\n    char kconf_id_strings_str35[sizeof(\"range\")];\n    char kconf_id_strings_str36[sizeof(\"choice\")];\n    char kconf_id_strings_str39[sizeof(\"bool\")];\n    char kconf_id_strings_str41[sizeof(\"source\")];\n    char kconf_id_strings_str42[sizeof(\"visible\")];\n    char kconf_id_strings_str43[sizeof(\"hex\")];\n    char kconf_id_strings_str46[sizeof(\"config\")];\n    char kconf_id_strings_str47[sizeof(\"boolean\")];\n    char kconf_id_strings_str51[sizeof(\"string\")];\n    char kconf_id_strings_str54[sizeof(\"help\")];\n    char kconf_id_strings_str56[sizeof(\"prompt\")];\n    char kconf_id_strings_str72[sizeof(\"depends\")];\n  };\nstatic const struct kconf_id_strings_t kconf_id_strings_contents =\n  {\n    \"if\",\n    \"int\",\n    \"endif\",\n    \"default\",\n    \"tristate\",\n    \"endchoice\",\n    \"def_tristate\",\n    \"def_bool\",\n    \"defconfig_list\",\n    \"on\",\n    \"optional\",\n    \"option\",\n    \"endmenu\",\n    \"mainmenu\",\n    \"menuconfig\",\n    \"modules\",\n    \"allnoconfig_y\",\n    \"menu\",\n    \"select\",\n    \"comment\",\n    \"env\",\n    \"range\",\n    \"choice\",\n    \"bool\",\n    \"source\",\n    \"visible\",\n    \"hex\",\n    \"config\",\n    \"boolean\",\n    \"string\",\n    \"help\",\n    \"prompt\",\n    \"depends\"\n  };\n#define kconf_id_strings ((const char *) &kconf_id_strings_contents)\n#ifdef __GNUC__\n__inline\n#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__\n__attribute__ ((__gnu_inline__))\n#endif\n#endif\nconst struct kconf_id *\nkconf_id_lookup (register const char *str, register unsigned int len)\n{\n  enum\n    {\n      TOTAL_KEYWORDS = 33,\n      MIN_WORD_LENGTH = 2,\n      MAX_WORD_LENGTH = 14,\n      MIN_HASH_VALUE = 2,\n      MAX_HASH_VALUE = 72\n    };\n\n  static const struct kconf_id wordlist[] =\n    {\n      {-1}, {-1},\n#line 25 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,\t\tT_IF,\t\tTF_COMMAND|TF_PARAM},\n#line 36 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3,\t\tT_TYPE,\t\tTF_COMMAND, S_INT},\n      {-1},\n#line 26 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5,\t\tT_ENDIF,\tTF_COMMAND},\n      {-1},\n#line 29 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,\tT_DEFAULT,\tTF_COMMAND, S_UNKNOWN},\n#line 31 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,\tT_TYPE,\t\tTF_COMMAND, S_TRISTATE},\n#line 20 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9,\tT_ENDCHOICE,\tTF_COMMAND},\n      {-1}, {-1},\n#line 32 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,\tT_DEFAULT,\tTF_COMMAND, S_TRISTATE},\n#line 35 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,\tT_DEFAULT,\tTF_COMMAND, S_BOOLEAN},\n#line 45 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,\tT_OPT_DEFCONFIG_LIST,TF_OPTION},\n      {-1}, {-1},\n#line 43 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,\t\tT_ON,\t\tTF_PARAM},\n#line 28 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,\tT_OPTIONAL,\tTF_COMMAND},\n      {-1}, {-1},\n#line 42 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,\t\tT_OPTION,\tTF_COMMAND},\n#line 17 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,\tT_ENDMENU,\tTF_COMMAND},\n#line 15 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,\tT_MAINMENU,\tTF_COMMAND},\n      {-1},\n#line 23 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25,\tT_MENUCONFIG,\tTF_COMMAND},\n      {-1},\n#line 44 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,\tT_OPT_MODULES,\tTF_OPTION},\n#line 47 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,\tT_OPT_ALLNOCONFIG_Y,TF_OPTION},\n#line 16 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29,\t\tT_MENU,\t\tTF_COMMAND},\n      {-1},\n#line 39 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,\t\tT_SELECT,\tTF_COMMAND},\n#line 21 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,\tT_COMMENT,\tTF_COMMAND},\n#line 46 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,\t\tT_OPT_ENV,\tTF_OPTION},\n      {-1},\n#line 40 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,\t\tT_RANGE,\tTF_COMMAND},\n#line 19 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,\t\tT_CHOICE,\tTF_COMMAND},\n      {-1}, {-1},\n#line 33 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39,\t\tT_TYPE,\t\tTF_COMMAND, S_BOOLEAN},\n      {-1},\n#line 18 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,\t\tT_SOURCE,\tTF_COMMAND},\n#line 41 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,\tT_VISIBLE,\tTF_COMMAND},\n#line 37 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43,\t\tT_TYPE,\t\tTF_COMMAND, S_HEX},\n      {-1}, {-1},\n#line 22 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,\t\tT_CONFIG,\tTF_COMMAND},\n#line 34 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47,\tT_TYPE,\t\tTF_COMMAND, S_BOOLEAN},\n      {-1}, {-1}, {-1},\n#line 38 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51,\t\tT_TYPE,\t\tTF_COMMAND, S_STRING},\n      {-1}, {-1},\n#line 24 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54,\t\tT_HELP,\t\tTF_COMMAND},\n      {-1},\n#line 30 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56,\t\tT_PROMPT,\tTF_COMMAND},\n      {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},\n      {-1}, {-1}, {-1}, {-1}, {-1}, {-1},\n#line 27 \"scripts/kconfig/zconf.gperf\"\n      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72,\tT_DEPENDS,\tTF_COMMAND}\n    };\n\n  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)\n    {\n      register int key = kconf_id_hash (str, len);\n\n      if (key <= MAX_HASH_VALUE && key >= 0)\n        {\n          register int o = wordlist[key].name;\n          if (o >= 0)\n            {\n              register const char *s = o + kconf_id_strings;\n\n              if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\\0')\n                return &wordlist[key];\n            }\n        }\n    }\n  return 0;\n}\n#line 48 \"scripts/kconfig/zconf.gperf\"\n\n"
  },
  {
    "path": "kconfig/zconf.l",
    "content": "%option nostdinit noyywrap never-interactive full ecs\n%option 8bit nodefault perf-report perf-report\n%option noinput\n%x COMMAND HELP STRING PARAM\n%{\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"lkc.h\"\n\n#define START_STRSIZE\t16\n\nstatic struct {\n\tstruct file *file;\n\tint lineno;\n} current_pos;\n\nstatic char *text;\nstatic int text_size, text_asize;\n\nstruct buffer {\n        struct buffer *parent;\n        YY_BUFFER_STATE state;\n};\n\nstruct buffer *current_buf;\n\nstatic int last_ts, first_ts;\n\nstatic void zconf_endhelp(void);\nstatic void zconf_endfile(void);\n\nstatic void new_string(void)\n{\n\ttext = xmalloc(START_STRSIZE);\n\ttext_asize = START_STRSIZE;\n\ttext_size = 0;\n\t*text = 0;\n}\n\nstatic void append_string(const char *str, int size)\n{\n\tint new_size = text_size + size + 1;\n\tif (new_size > text_asize) {\n\t\tnew_size += START_STRSIZE - 1;\n\t\tnew_size &= -START_STRSIZE;\n\t\ttext = realloc(text, new_size);\n\t\ttext_asize = new_size;\n\t}\n\tmemcpy(text + text_size, str, size);\n\ttext_size += size;\n\ttext[text_size] = 0;\n}\n\nstatic void alloc_string(const char *str, int size)\n{\n\ttext = xmalloc(size + 1);\n\tmemcpy(text, str, size);\n\ttext[size] = 0;\n}\n%}\n\nn\t[A-Za-z0-9_]\n\n%%\n\tint str = 0;\n\tint ts, i;\n\n[ \\t]*#.*\\n\t|\n[ \\t]*\\n\t{\n\tcurrent_file->lineno++;\n\treturn T_EOL;\n}\n[ \\t]*#.*\n\n\n[ \\t]+\t{\n\tBEGIN(COMMAND);\n}\n\n.\t{\n\tunput(yytext[0]);\n\tBEGIN(COMMAND);\n}\n\n\n<COMMAND>{\n\t{n}+\t{\n\t\tconst struct kconf_id *id = kconf_id_lookup(yytext, yyleng);\n\t\tBEGIN(PARAM);\n\t\tcurrent_pos.file = current_file;\n\t\tcurrent_pos.lineno = current_file->lineno;\n\t\tif (id && id->flags & TF_COMMAND) {\n\t\t\tzconflval.id = id;\n\t\t\treturn id->token;\n\t\t}\n\t\talloc_string(yytext, yyleng);\n\t\tzconflval.string = text;\n\t\treturn T_WORD;\n\t}\n\t.\n\t\\n\t{\n\t\tBEGIN(INITIAL);\n\t\tcurrent_file->lineno++;\n\t\treturn T_EOL;\n\t}\n}\n\n<PARAM>{\n\t\"&&\"\treturn T_AND;\n\t\"||\"\treturn T_OR;\n\t\"(\"\treturn T_OPEN_PAREN;\n\t\")\"\treturn T_CLOSE_PAREN;\n\t\"!\"\treturn T_NOT;\n\t\"=\"\treturn T_EQUAL;\n\t\"!=\"\treturn T_UNEQUAL;\n\t\\\"|\\'\t{\n\t\tstr = yytext[0];\n\t\tnew_string();\n\t\tBEGIN(STRING);\n\t}\n\t\\n\tBEGIN(INITIAL); current_file->lineno++; return T_EOL;\n\t---\t/* ignore */\n\t({n}|[-/.])+\t{\n\t\tconst struct kconf_id *id = kconf_id_lookup(yytext, yyleng);\n\t\tif (id && id->flags & TF_PARAM) {\n\t\t\tzconflval.id = id;\n\t\t\treturn id->token;\n\t\t}\n\t\talloc_string(yytext, yyleng);\n\t\tzconflval.string = text;\n\t\treturn T_WORD;\n\t}\n\t#.*\t/* comment */\n\t\\\\\\n\tcurrent_file->lineno++;\n\t.\n\t<<EOF>> {\n\t\tBEGIN(INITIAL);\n\t}\n}\n\n<STRING>{\n\t[^'\"\\\\\\n]+/\\n\t{\n\t\tappend_string(yytext, yyleng);\n\t\tzconflval.string = text;\n\t\treturn T_WORD_QUOTE;\n\t}\n\t[^'\"\\\\\\n]+\t{\n\t\tappend_string(yytext, yyleng);\n\t}\n\t\\\\.?/\\n\t{\n\t\tappend_string(yytext + 1, yyleng - 1);\n\t\tzconflval.string = text;\n\t\treturn T_WORD_QUOTE;\n\t}\n\t\\\\.?\t{\n\t\tappend_string(yytext + 1, yyleng - 1);\n\t}\n\t\\'|\\\"\t{\n\t\tif (str == yytext[0]) {\n\t\t\tBEGIN(PARAM);\n\t\t\tzconflval.string = text;\n\t\t\treturn T_WORD_QUOTE;\n\t\t} else\n\t\t\tappend_string(yytext, 1);\n\t}\n\t\\n\t{\n\t\tprintf(\"%s:%d:warning: multi-line strings not supported\\n\", zconf_curname(), zconf_lineno());\n\t\tcurrent_file->lineno++;\n\t\tBEGIN(INITIAL);\n\t\treturn T_EOL;\n\t}\n\t<<EOF>>\t{\n\t\tBEGIN(INITIAL);\n\t}\n}\n\n<HELP>{\n\t[ \\t]+\t{\n\t\tts = 0;\n\t\tfor (i = 0; i < yyleng; i++) {\n\t\t\tif (yytext[i] == '\\t')\n\t\t\t\tts = (ts & ~7) + 8;\n\t\t\telse\n\t\t\t\tts++;\n\t\t}\n\t\tlast_ts = ts;\n\t\tif (first_ts) {\n\t\t\tif (ts < first_ts) {\n\t\t\t\tzconf_endhelp();\n\t\t\t\treturn T_HELPTEXT;\n\t\t\t}\n\t\t\tts -= first_ts;\n\t\t\twhile (ts > 8) {\n\t\t\t\tappend_string(\"        \", 8);\n\t\t\t\tts -= 8;\n\t\t\t}\n\t\t\tappend_string(\"        \", ts);\n\t\t}\n\t}\n\t[ \\t]*\\n/[^ \\t\\n] {\n\t\tcurrent_file->lineno++;\n\t\tzconf_endhelp();\n\t\treturn T_HELPTEXT;\n\t}\n\t[ \\t]*\\n\t{\n\t\tcurrent_file->lineno++;\n\t\tappend_string(\"\\n\", 1);\n\t}\n\t[^ \\t\\n].* {\n\t\twhile (yyleng) {\n\t\t\tif ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\\t'))\n\t\t\t\tbreak;\n\t\t\tyyleng--;\n\t\t}\n\t\tappend_string(yytext, yyleng);\n\t\tif (!first_ts)\n\t\t\tfirst_ts = last_ts;\n\t}\n\t<<EOF>>\t{\n\t\tzconf_endhelp();\n\t\treturn T_HELPTEXT;\n\t}\n}\n\n<<EOF>>\t{\n\tif (current_file) {\n\t\tzconf_endfile();\n\t\treturn T_EOL;\n\t}\n\tfclose(yyin);\n\tyyterminate();\n}\n\n%%\nvoid zconf_starthelp(void)\n{\n\tnew_string();\n\tlast_ts = first_ts = 0;\n\tBEGIN(HELP);\n}\n\nstatic void zconf_endhelp(void)\n{\n\tzconflval.string = text;\n\tBEGIN(INITIAL);\n}\n\n\n/*\n * Try to open specified file with following names:\n * ./name\n * $(srctree)/name\n * The latter is used when srctree is separate from objtree\n * when compiling the kernel.\n * Return NULL if file is not found.\n */\nFILE *zconf_fopen(const char *name)\n{\n\tchar *env, fullname[PATH_MAX+1];\n\tFILE *f;\n\n\tf = fopen(name, \"r\");\n\tif (!f && name != NULL && name[0] != '/') {\n\t\tenv = getenv(SRCTREE);\n\t\tif (env) {\n\t\t\tsprintf(fullname, \"%s/%s\", env, name);\n\t\t\tf = fopen(fullname, \"r\");\n\t\t}\n\t}\n\treturn f;\n}\n\nvoid zconf_initscan(const char *name)\n{\n\tyyin = zconf_fopen(name);\n\tif (!yyin) {\n\t\tprintf(\"can't find file %s\\n\", name);\n\t\texit(1);\n\t}\n\n\tcurrent_buf = xmalloc(sizeof(*current_buf));\n\tmemset(current_buf, 0, sizeof(*current_buf));\n\n\tcurrent_file = file_lookup(name);\n\tcurrent_file->lineno = 1;\n}\n\nvoid zconf_nextfile(const char *name)\n{\n\tstruct file *iter;\n\tstruct file *file = file_lookup(name);\n\tstruct buffer *buf = xmalloc(sizeof(*buf));\n\tmemset(buf, 0, sizeof(*buf));\n\n\tcurrent_buf->state = YY_CURRENT_BUFFER;\n\tyyin = zconf_fopen(file->name);\n\tif (!yyin) {\n\t\tprintf(\"%s:%d: can't open file \\\"%s\\\"\\n\",\n\t\t    zconf_curname(), zconf_lineno(), file->name);\n\t\texit(1);\n\t}\n\tyy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));\n\tbuf->parent = current_buf;\n\tcurrent_buf = buf;\n\n\tfor (iter = current_file->parent; iter; iter = iter->parent ) {\n\t\tif (!strcmp(current_file->name,iter->name) ) {\n\t\t\tprintf(\"%s:%d: recursive inclusion detected. \"\n\t\t\t       \"Inclusion path:\\n  current file : '%s'\\n\",\n\t\t\t       zconf_curname(), zconf_lineno(),\n\t\t\t       zconf_curname());\n\t\t\titer = current_file->parent;\n\t\t\twhile (iter && \\\n\t\t\t       strcmp(iter->name,current_file->name)) {\n\t\t\t\tprintf(\"  included from: '%s:%d'\\n\",\n\t\t\t\t       iter->name, iter->lineno-1);\n\t\t\t\titer = iter->parent;\n\t\t\t}\n\t\t\tif (iter)\n\t\t\t\tprintf(\"  included from: '%s:%d'\\n\",\n\t\t\t\t       iter->name, iter->lineno+1);\n\t\t\texit(1);\n\t\t}\n\t}\n\tfile->lineno = 1;\n\tfile->parent = current_file;\n\tcurrent_file = file;\n}\n\nstatic void zconf_endfile(void)\n{\n\tstruct buffer *parent;\n\n\tcurrent_file = current_file->parent;\n\n\tparent = current_buf->parent;\n\tif (parent) {\n\t\tfclose(yyin);\n\t\tyy_delete_buffer(YY_CURRENT_BUFFER);\n\t\tyy_switch_to_buffer(parent->state);\n\t}\n\tfree(current_buf);\n\tcurrent_buf = parent;\n}\n\nint zconf_lineno(void)\n{\n\treturn current_pos.lineno;\n}\n\nconst char *zconf_curname(void)\n{\n\treturn current_pos.file ? current_pos.file->name : \"<none>\";\n}\n"
  },
  {
    "path": "kconfig/zconf.lex.c_shipped",
    "content": "\n#line 3 \"scripts/kconfig/zconf.lex.c_shipped\"\n\n#define  YY_INT_ALIGNED short int\n\n/* A lexical scanner generated by flex */\n\n#define yy_create_buffer zconf_create_buffer\n#define yy_delete_buffer zconf_delete_buffer\n#define yy_flex_debug zconf_flex_debug\n#define yy_init_buffer zconf_init_buffer\n#define yy_flush_buffer zconf_flush_buffer\n#define yy_load_buffer_state zconf_load_buffer_state\n#define yy_switch_to_buffer zconf_switch_to_buffer\n#define yyin zconfin\n#define yyleng zconfleng\n#define yylex zconflex\n#define yylineno zconflineno\n#define yyout zconfout\n#define yyrestart zconfrestart\n#define yytext zconftext\n#define yywrap zconfwrap\n#define yyalloc zconfalloc\n#define yyrealloc zconfrealloc\n#define yyfree zconffree\n\n#define FLEX_SCANNER\n#define YY_FLEX_MAJOR_VERSION 2\n#define YY_FLEX_MINOR_VERSION 5\n#define YY_FLEX_SUBMINOR_VERSION 35\n#if YY_FLEX_SUBMINOR_VERSION > 0\n#define FLEX_BETA\n#endif\n\n/* First, we deal with  platform-specific or compiler-specific issues. */\n\n/* begin standard C headers. */\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#include <stdlib.h>\n\n/* end standard C headers. */\n\n/* flex integer type definitions */\n\n#ifndef FLEXINT_H\n#define FLEXINT_H\n\n/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */\n\n#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n\n/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,\n * if you want the limit (max/min) macros for int types. \n */\n#ifndef __STDC_LIMIT_MACROS\n#define __STDC_LIMIT_MACROS 1\n#endif\n\n#include <inttypes.h>\ntypedef int8_t flex_int8_t;\ntypedef uint8_t flex_uint8_t;\ntypedef int16_t flex_int16_t;\ntypedef uint16_t flex_uint16_t;\ntypedef int32_t flex_int32_t;\ntypedef uint32_t flex_uint32_t;\n#else\ntypedef signed char flex_int8_t;\ntypedef short int flex_int16_t;\ntypedef int flex_int32_t;\ntypedef unsigned char flex_uint8_t; \ntypedef unsigned short int flex_uint16_t;\ntypedef unsigned int flex_uint32_t;\n#endif /* ! C99 */\n\n/* Limits of integral types. */\n#ifndef INT8_MIN\n#define INT8_MIN               (-128)\n#endif\n#ifndef INT16_MIN\n#define INT16_MIN              (-32767-1)\n#endif\n#ifndef INT32_MIN\n#define INT32_MIN              (-2147483647-1)\n#endif\n#ifndef INT8_MAX\n#define INT8_MAX               (127)\n#endif\n#ifndef INT16_MAX\n#define INT16_MAX              (32767)\n#endif\n#ifndef INT32_MAX\n#define INT32_MAX              (2147483647)\n#endif\n#ifndef UINT8_MAX\n#define UINT8_MAX              (255U)\n#endif\n#ifndef UINT16_MAX\n#define UINT16_MAX             (65535U)\n#endif\n#ifndef UINT32_MAX\n#define UINT32_MAX             (4294967295U)\n#endif\n\n#endif /* ! FLEXINT_H */\n\n#ifdef __cplusplus\n\n/* The \"const\" storage-class-modifier is valid. */\n#define YY_USE_CONST\n\n#else\t/* ! __cplusplus */\n\n/* C99 requires __STDC__ to be defined as 1. */\n#if defined (__STDC__)\n\n#define YY_USE_CONST\n\n#endif\t/* defined (__STDC__) */\n#endif\t/* ! __cplusplus */\n\n#ifdef YY_USE_CONST\n#define yyconst const\n#else\n#define yyconst\n#endif\n\n/* Returned upon end-of-file. */\n#define YY_NULL 0\n\n/* Promotes a possibly negative, possibly signed char to an unsigned\n * integer for use as an array index.  If the signed char is negative,\n * we want to instead treat it as an 8-bit unsigned char, hence the\n * double cast.\n */\n#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)\n\n/* Enter a start condition.  This macro really ought to take a parameter,\n * but we do it the disgusting crufty way forced on us by the ()-less\n * definition of BEGIN.\n */\n#define BEGIN (yy_start) = 1 + 2 *\n\n/* Translate the current start state into a value that can be later handed\n * to BEGIN to return to the state.  The YYSTATE alias is for lex\n * compatibility.\n */\n#define YY_START (((yy_start) - 1) / 2)\n#define YYSTATE YY_START\n\n/* Action number for EOF rule of a given start state. */\n#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)\n\n/* Special action meaning \"start processing a new file\". */\n#define YY_NEW_FILE zconfrestart(zconfin  )\n\n#define YY_END_OF_BUFFER_CHAR 0\n\n/* Size of default input buffer. */\n#ifndef YY_BUF_SIZE\n#define YY_BUF_SIZE 16384\n#endif\n\n/* The state buf must be large enough to hold one state per character in the main buffer.\n */\n#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))\n\n#ifndef YY_TYPEDEF_YY_BUFFER_STATE\n#define YY_TYPEDEF_YY_BUFFER_STATE\ntypedef struct yy_buffer_state *YY_BUFFER_STATE;\n#endif\n\nextern int zconfleng;\n\nextern FILE *zconfin, *zconfout;\n\n#define EOB_ACT_CONTINUE_SCAN 0\n#define EOB_ACT_END_OF_FILE 1\n#define EOB_ACT_LAST_MATCH 2\n\n    #define YY_LESS_LINENO(n)\n    \n/* Return all but the first \"n\" matched characters back to the input stream. */\n#define yyless(n) \\\n\tdo \\\n\t\t{ \\\n\t\t/* Undo effects of setting up zconftext. */ \\\n        int yyless_macro_arg = (n); \\\n        YY_LESS_LINENO(yyless_macro_arg);\\\n\t\t*yy_cp = (yy_hold_char); \\\n\t\tYY_RESTORE_YY_MORE_OFFSET \\\n\t\t(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \\\n\t\tYY_DO_BEFORE_ACTION; /* set up zconftext again */ \\\n\t\t} \\\n\twhile ( 0 )\n\n#define unput(c) yyunput( c, (yytext_ptr)  )\n\n#ifndef YY_TYPEDEF_YY_SIZE_T\n#define YY_TYPEDEF_YY_SIZE_T\ntypedef size_t yy_size_t;\n#endif\n\n#ifndef YY_STRUCT_YY_BUFFER_STATE\n#define YY_STRUCT_YY_BUFFER_STATE\nstruct yy_buffer_state\n\t{\n\tFILE *yy_input_file;\n\n\tchar *yy_ch_buf;\t\t/* input buffer */\n\tchar *yy_buf_pos;\t\t/* current position in input buffer */\n\n\t/* Size of input buffer in bytes, not including room for EOB\n\t * characters.\n\t */\n\tyy_size_t yy_buf_size;\n\n\t/* Number of characters read into yy_ch_buf, not including EOB\n\t * characters.\n\t */\n\tint yy_n_chars;\n\n\t/* Whether we \"own\" the buffer - i.e., we know we created it,\n\t * and can realloc() it to grow it, and should free() it to\n\t * delete it.\n\t */\n\tint yy_is_our_buffer;\n\n\t/* Whether this is an \"interactive\" input source; if so, and\n\t * if we're using stdio for input, then we want to use getc()\n\t * instead of fread(), to make sure we stop fetching input after\n\t * each newline.\n\t */\n\tint yy_is_interactive;\n\n\t/* Whether we're considered to be at the beginning of a line.\n\t * If so, '^' rules will be active on the next match, otherwise\n\t * not.\n\t */\n\tint yy_at_bol;\n\n    int yy_bs_lineno; /**< The line count. */\n    int yy_bs_column; /**< The column count. */\n    \n\t/* Whether to try to fill the input buffer when we reach the\n\t * end of it.\n\t */\n\tint yy_fill_buffer;\n\n\tint yy_buffer_status;\n\n#define YY_BUFFER_NEW 0\n#define YY_BUFFER_NORMAL 1\n\t/* When an EOF's been seen but there's still some text to process\n\t * then we mark the buffer as YY_EOF_PENDING, to indicate that we\n\t * shouldn't try reading from the input source any more.  We might\n\t * still have a bunch of tokens to match, though, because of\n\t * possible backing-up.\n\t *\n\t * When we actually see the EOF, we change the status to \"new\"\n\t * (via zconfrestart()), so that the user can continue scanning by\n\t * just pointing zconfin at a new input file.\n\t */\n#define YY_BUFFER_EOF_PENDING 2\n\n\t};\n#endif /* !YY_STRUCT_YY_BUFFER_STATE */\n\n/* Stack of input buffers. */\nstatic size_t yy_buffer_stack_top = 0; /**< index of top of stack. */\nstatic size_t yy_buffer_stack_max = 0; /**< capacity of stack. */\nstatic YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */\n\n/* We provide macros for accessing buffer states in case in the\n * future we want to put the buffer states in a more general\n * \"scanner state\".\n *\n * Returns the top of the stack, or NULL.\n */\n#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \\\n                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \\\n                          : NULL)\n\n/* Same as previous macro, but useful when we know that the buffer stack is not\n * NULL or when we need an lvalue. For internal use only.\n */\n#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]\n\n/* yy_hold_char holds the character lost when zconftext is formed. */\nstatic char yy_hold_char;\nstatic int yy_n_chars;\t\t/* number of characters read into yy_ch_buf */\nint zconfleng;\n\n/* Points to current character in buffer. */\nstatic char *yy_c_buf_p = (char *) 0;\nstatic int yy_init = 0;\t\t/* whether we need to initialize */\nstatic int yy_start = 0;\t/* start state number */\n\n/* Flag which is used to allow zconfwrap()'s to do buffer switches\n * instead of setting up a fresh zconfin.  A bit of a hack ...\n */\nstatic int yy_did_buffer_switch_on_eof;\n\nvoid zconfrestart (FILE *input_file  );\nvoid zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer  );\nYY_BUFFER_STATE zconf_create_buffer (FILE *file,int size  );\nvoid zconf_delete_buffer (YY_BUFFER_STATE b  );\nvoid zconf_flush_buffer (YY_BUFFER_STATE b  );\nvoid zconfpush_buffer_state (YY_BUFFER_STATE new_buffer  );\nvoid zconfpop_buffer_state (void );\n\nstatic void zconfensure_buffer_stack (void );\nstatic void zconf_load_buffer_state (void );\nstatic void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );\n\n#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER )\n\nYY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );\nYY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );\nYY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );\n\nvoid *zconfalloc (yy_size_t  );\nvoid *zconfrealloc (void *,yy_size_t  );\nvoid zconffree (void *  );\n\n#define yy_new_buffer zconf_create_buffer\n\n#define yy_set_interactive(is_interactive) \\\n\t{ \\\n\tif ( ! YY_CURRENT_BUFFER ){ \\\n        zconfensure_buffer_stack (); \\\n\t\tYY_CURRENT_BUFFER_LVALUE =    \\\n            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \\\n\t} \\\n\tYY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \\\n\t}\n\n#define yy_set_bol(at_bol) \\\n\t{ \\\n\tif ( ! YY_CURRENT_BUFFER ){\\\n        zconfensure_buffer_stack (); \\\n\t\tYY_CURRENT_BUFFER_LVALUE =    \\\n            zconf_create_buffer(zconfin,YY_BUF_SIZE ); \\\n\t} \\\n\tYY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \\\n\t}\n\n#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)\n\n/* Begin user sect3 */\n\n#define zconfwrap(n) 1\n#define YY_SKIP_YYWRAP\n\ntypedef unsigned char YY_CHAR;\n\nFILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0;\n\ntypedef int yy_state_type;\n\nextern int zconflineno;\n\nint zconflineno = 1;\n\nextern char *zconftext;\n#define yytext_ptr zconftext\nstatic yyconst flex_int16_t yy_nxt[][17] =\n    {\n    {\n        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,\n        0,    0,    0,    0,    0,    0,    0\n    },\n\n    {\n       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,\n       12,   12,   12,   12,   12,   12,   12\n    },\n\n    {\n       11,   12,   13,   14,   12,   12,   15,   12,   12,   12,\n       12,   12,   12,   12,   12,   12,   12\n    },\n\n    {\n       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,\n       16,   16,   16,   18,   16,   16,   16\n    },\n\n    {\n       11,   16,   16,   17,   16,   16,   16,   16,   16,   16,\n       16,   16,   16,   18,   16,   16,   16\n\n    },\n\n    {\n       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,\n       19,   19,   19,   19,   19,   19,   19\n    },\n\n    {\n       11,   19,   20,   21,   19,   19,   19,   19,   19,   19,\n       19,   19,   19,   19,   19,   19,   19\n    },\n\n    {\n       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,\n       22,   22,   22,   22,   22,   25,   22\n    },\n\n    {\n       11,   22,   22,   23,   22,   24,   22,   22,   24,   22,\n       22,   22,   22,   22,   22,   25,   22\n    },\n\n    {\n       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,\n       33,   34,   35,   35,   36,   37,   38\n\n    },\n\n    {\n       11,   26,   26,   27,   28,   29,   30,   31,   29,   32,\n       33,   34,   35,   35,   36,   37,   38\n    },\n\n    {\n      -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,\n      -11,  -11,  -11,  -11,  -11,  -11,  -11\n    },\n\n    {\n       11,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,  -12,\n      -12,  -12,  -12,  -12,  -12,  -12,  -12\n    },\n\n    {\n       11,  -13,   39,   40,  -13,  -13,   41,  -13,  -13,  -13,\n      -13,  -13,  -13,  -13,  -13,  -13,  -13\n    },\n\n    {\n       11,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,\n      -14,  -14,  -14,  -14,  -14,  -14,  -14\n\n    },\n\n    {\n       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,\n       42,   42,   42,   42,   42,   42,   42\n    },\n\n    {\n       11,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,\n      -16,  -16,  -16,  -16,  -16,  -16,  -16\n    },\n\n    {\n       11,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,  -17,\n      -17,  -17,  -17,  -17,  -17,  -17,  -17\n    },\n\n    {\n       11,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,  -18,\n      -18,  -18,  -18,   44,  -18,  -18,  -18\n    },\n\n    {\n       11,   45,   45,  -19,   45,   45,   45,   45,   45,   45,\n       45,   45,   45,   45,   45,   45,   45\n\n    },\n\n    {\n       11,  -20,   46,   47,  -20,  -20,  -20,  -20,  -20,  -20,\n      -20,  -20,  -20,  -20,  -20,  -20,  -20\n    },\n\n    {\n       11,   48,  -21,  -21,   48,   48,   48,   48,   48,   48,\n       48,   48,   48,   48,   48,   48,   48\n    },\n\n    {\n       11,   49,   49,   50,   49,  -22,   49,   49,  -22,   49,\n       49,   49,   49,   49,   49,  -22,   49\n    },\n\n    {\n       11,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,\n      -23,  -23,  -23,  -23,  -23,  -23,  -23\n    },\n\n    {\n       11,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,\n      -24,  -24,  -24,  -24,  -24,  -24,  -24\n\n    },\n\n    {\n       11,   51,   51,   52,   51,   51,   51,   51,   51,   51,\n       51,   51,   51,   51,   51,   51,   51\n    },\n\n    {\n       11,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,\n      -26,  -26,  -26,  -26,  -26,  -26,  -26\n    },\n\n    {\n       11,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,\n      -27,  -27,  -27,  -27,  -27,  -27,  -27\n    },\n\n    {\n       11,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,\n      -28,  -28,  -28,  -28,   53,  -28,  -28\n    },\n\n    {\n       11,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,\n      -29,  -29,  -29,  -29,  -29,  -29,  -29\n\n    },\n\n    {\n       11,   54,   54,  -30,   54,   54,   54,   54,   54,   54,\n       54,   54,   54,   54,   54,   54,   54\n    },\n\n    {\n       11,  -31,  -31,  -31,  -31,  -31,  -31,   55,  -31,  -31,\n      -31,  -31,  -31,  -31,  -31,  -31,  -31\n    },\n\n    {\n       11,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,  -32,\n      -32,  -32,  -32,  -32,  -32,  -32,  -32\n    },\n\n    {\n       11,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,\n      -33,  -33,  -33,  -33,  -33,  -33,  -33\n    },\n\n    {\n       11,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,\n      -34,   56,   57,   57,  -34,  -34,  -34\n\n    },\n\n    {\n       11,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,\n      -35,   57,   57,   57,  -35,  -35,  -35\n    },\n\n    {\n       11,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,\n      -36,  -36,  -36,  -36,  -36,  -36,  -36\n    },\n\n    {\n       11,  -37,  -37,   58,  -37,  -37,  -37,  -37,  -37,  -37,\n      -37,  -37,  -37,  -37,  -37,  -37,  -37\n    },\n\n    {\n       11,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,\n      -38,  -38,  -38,  -38,  -38,  -38,   59\n    },\n\n    {\n       11,  -39,   39,   40,  -39,  -39,   41,  -39,  -39,  -39,\n      -39,  -39,  -39,  -39,  -39,  -39,  -39\n\n    },\n\n    {\n       11,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,\n      -40,  -40,  -40,  -40,  -40,  -40,  -40\n    },\n\n    {\n       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,\n       42,   42,   42,   42,   42,   42,   42\n    },\n\n    {\n       11,   42,   42,   43,   42,   42,   42,   42,   42,   42,\n       42,   42,   42,   42,   42,   42,   42\n    },\n\n    {\n       11,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,\n      -43,  -43,  -43,  -43,  -43,  -43,  -43\n    },\n\n    {\n       11,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,\n      -44,  -44,  -44,   44,  -44,  -44,  -44\n\n    },\n\n    {\n       11,   45,   45,  -45,   45,   45,   45,   45,   45,   45,\n       45,   45,   45,   45,   45,   45,   45\n    },\n\n    {\n       11,  -46,   46,   47,  -46,  -46,  -46,  -46,  -46,  -46,\n      -46,  -46,  -46,  -46,  -46,  -46,  -46\n    },\n\n    {\n       11,   48,  -47,  -47,   48,   48,   48,   48,   48,   48,\n       48,   48,   48,   48,   48,   48,   48\n    },\n\n    {\n       11,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,  -48,\n      -48,  -48,  -48,  -48,  -48,  -48,  -48\n    },\n\n    {\n       11,   49,   49,   50,   49,  -49,   49,   49,  -49,   49,\n       49,   49,   49,   49,   49,  -49,   49\n\n    },\n\n    {\n       11,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,\n      -50,  -50,  -50,  -50,  -50,  -50,  -50\n    },\n\n    {\n       11,  -51,  -51,   52,  -51,  -51,  -51,  -51,  -51,  -51,\n      -51,  -51,  -51,  -51,  -51,  -51,  -51\n    },\n\n    {\n       11,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,  -52,\n      -52,  -52,  -52,  -52,  -52,  -52,  -52\n    },\n\n    {\n       11,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,\n      -53,  -53,  -53,  -53,  -53,  -53,  -53\n    },\n\n    {\n       11,   54,   54,  -54,   54,   54,   54,   54,   54,   54,\n       54,   54,   54,   54,   54,   54,   54\n\n    },\n\n    {\n       11,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,\n      -55,  -55,  -55,  -55,  -55,  -55,  -55\n    },\n\n    {\n       11,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,\n      -56,   60,   57,   57,  -56,  -56,  -56\n    },\n\n    {\n       11,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,  -57,\n      -57,   57,   57,   57,  -57,  -57,  -57\n    },\n\n    {\n       11,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,  -58,\n      -58,  -58,  -58,  -58,  -58,  -58,  -58\n    },\n\n    {\n       11,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,  -59,\n      -59,  -59,  -59,  -59,  -59,  -59,  -59\n\n    },\n\n    {\n       11,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,  -60,\n      -60,   57,   57,   57,  -60,  -60,  -60\n    },\n\n    } ;\n\nstatic yy_state_type yy_get_previous_state (void );\nstatic yy_state_type yy_try_NUL_trans (yy_state_type current_state  );\nstatic int yy_get_next_buffer (void );\nstatic void yy_fatal_error (yyconst char msg[]  );\n\n/* Done after the current pattern has been matched and before the\n * corresponding action - sets up zconftext.\n */\n#define YY_DO_BEFORE_ACTION \\\n\t(yytext_ptr) = yy_bp; \\\n\tzconfleng = (size_t) (yy_cp - yy_bp); \\\n\t(yy_hold_char) = *yy_cp; \\\n\t*yy_cp = '\\0'; \\\n\t(yy_c_buf_p) = yy_cp;\n\n#define YY_NUM_RULES 33\n#define YY_END_OF_BUFFER 34\n/* This struct is not used in this scanner,\n   but its presence is necessary. */\nstruct yy_trans_info\n\t{\n\tflex_int32_t yy_verify;\n\tflex_int32_t yy_nxt;\n\t};\nstatic yyconst flex_int16_t yy_accept[61] =\n    {   0,\n        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,\n       34,    5,    4,    2,    3,    7,    8,    6,   32,   29,\n       31,   24,   28,   27,   26,   22,   17,   13,   16,   20,\n       22,   11,   12,   19,   19,   14,   22,   22,    4,    2,\n        3,    3,    1,    6,   32,   29,   31,   30,   24,   23,\n       26,   25,   15,   20,    9,   19,   19,   21,   10,   18\n    } ;\n\nstatic yyconst flex_int32_t yy_ec[256] =\n    {   0,\n        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    2,    4,    5,    6,    1,    1,    7,    8,    9,\n       10,    1,    1,    1,   11,   12,   12,   13,   13,   13,\n       13,   13,   13,   13,   13,   13,   13,    1,    1,    1,\n       14,    1,    1,    1,   13,   13,   13,   13,   13,   13,\n       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,\n       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,\n        1,   15,    1,    1,   13,    1,   13,   13,   13,   13,\n\n       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,\n       13,   13,   13,   13,   13,   13,   13,   13,   13,   13,\n       13,   13,    1,   16,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1\n    } ;\n\nextern int zconf_flex_debug;\nint zconf_flex_debug = 0;\n\n/* The intent behind this definition is that it'll catch\n * any uses of REJECT which flex missed.\n */\n#define REJECT reject_used_but_not_detected\n#define yymore() yymore_used_but_not_detected\n#define YY_MORE_ADJ 0\n#define YY_RESTORE_YY_MORE_OFFSET\nchar *zconftext;\n#define YY_NO_INPUT 1\n\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"lkc.h\"\n\n#define START_STRSIZE\t16\n\nstatic struct {\n\tstruct file *file;\n\tint lineno;\n} current_pos;\n\nstatic char *text;\nstatic int text_size, text_asize;\n\nstruct buffer {\n        struct buffer *parent;\n        YY_BUFFER_STATE state;\n};\n\nstruct buffer *current_buf;\n\nstatic int last_ts, first_ts;\n\nstatic void zconf_endhelp(void);\nstatic void zconf_endfile(void);\n\nstatic void new_string(void)\n{\n\ttext = xmalloc(START_STRSIZE);\n\ttext_asize = START_STRSIZE;\n\ttext_size = 0;\n\t*text = 0;\n}\n\nstatic void append_string(const char *str, int size)\n{\n\tint new_size = text_size + size + 1;\n\tif (new_size > text_asize) {\n\t\tnew_size += START_STRSIZE - 1;\n\t\tnew_size &= -START_STRSIZE;\n\t\ttext = realloc(text, new_size);\n\t\ttext_asize = new_size;\n\t}\n\tmemcpy(text + text_size, str, size);\n\ttext_size += size;\n\ttext[text_size] = 0;\n}\n\nstatic void alloc_string(const char *str, int size)\n{\n\ttext = xmalloc(size + 1);\n\tmemcpy(text, str, size);\n\ttext[size] = 0;\n}\n\n#define INITIAL 0\n#define COMMAND 1\n#define HELP 2\n#define STRING 3\n#define PARAM 4\n\n#ifndef YY_NO_UNISTD_H\n/* Special case for \"unistd.h\", since it is non-ANSI. We include it way\n * down here because we want the user's section 1 to have been scanned first.\n * The user has a chance to override it with an option.\n */\n#include <unistd.h>\n#endif\n\n#ifndef YY_EXTRA_TYPE\n#define YY_EXTRA_TYPE void *\n#endif\n\nstatic int yy_init_globals (void );\n\n/* Accessor methods to globals.\n   These are made visible to non-reentrant scanners for convenience. */\n\nint zconflex_destroy (void );\n\nint zconfget_debug (void );\n\nvoid zconfset_debug (int debug_flag  );\n\nYY_EXTRA_TYPE zconfget_extra (void );\n\nvoid zconfset_extra (YY_EXTRA_TYPE user_defined  );\n\nFILE *zconfget_in (void );\n\nvoid zconfset_in  (FILE * in_str  );\n\nFILE *zconfget_out (void );\n\nvoid zconfset_out  (FILE * out_str  );\n\nint zconfget_leng (void );\n\nchar *zconfget_text (void );\n\nint zconfget_lineno (void );\n\nvoid zconfset_lineno (int line_number  );\n\n/* Macros after this point can all be overridden by user definitions in\n * section 1.\n */\n\n#ifndef YY_SKIP_YYWRAP\n#ifdef __cplusplus\nextern \"C\" int zconfwrap (void );\n#else\nextern int zconfwrap (void );\n#endif\n#endif\n\n    static void yyunput (int c,char *buf_ptr  );\n    \n#ifndef yytext_ptr\nstatic void yy_flex_strncpy (char *,yyconst char *,int );\n#endif\n\n#ifdef YY_NEED_STRLEN\nstatic int yy_flex_strlen (yyconst char * );\n#endif\n\n#ifndef YY_NO_INPUT\n\n#ifdef __cplusplus\nstatic int yyinput (void );\n#else\nstatic int input (void );\n#endif\n\n#endif\n\n/* Amount of stuff to slurp up with each read. */\n#ifndef YY_READ_BUF_SIZE\n#define YY_READ_BUF_SIZE 8192\n#endif\n\n/* Copy whatever the last rule matched to the standard output. */\n#ifndef ECHO\n/* This used to be an fputs(), but since the string might contain NUL's,\n * we now use fwrite().\n */\n#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0)\n#endif\n\n/* Gets input and stuffs it into \"buf\".  number of characters read, or YY_NULL,\n * is returned in \"result\".\n */\n#ifndef YY_INPUT\n#define YY_INPUT(buf,result,max_size) \\\n\terrno=0; \\\n\twhile ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \\\n\t{ \\\n\t\tif( errno != EINTR) \\\n\t\t{ \\\n\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\\n\t\t\tbreak; \\\n\t\t} \\\n\t\terrno=0; \\\n\t\tclearerr(zconfin); \\\n\t}\\\n\\\n\n#endif\n\n/* No semi-colon after return; correct usage is to write \"yyterminate();\" -\n * we don't want an extra ';' after the \"return\" because that will cause\n * some compilers to complain about unreachable statements.\n */\n#ifndef yyterminate\n#define yyterminate() return YY_NULL\n#endif\n\n/* Number of entries by which start-condition stack grows. */\n#ifndef YY_START_STACK_INCR\n#define YY_START_STACK_INCR 25\n#endif\n\n/* Report a fatal error. */\n#ifndef YY_FATAL_ERROR\n#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )\n#endif\n\n/* end tables serialization structures and prototypes */\n\n/* Default declaration of generated scanner - a define so the user can\n * easily add parameters.\n */\n#ifndef YY_DECL\n#define YY_DECL_IS_OURS 1\n\nextern int zconflex (void);\n\n#define YY_DECL int zconflex (void)\n#endif /* !YY_DECL */\n\n/* Code executed at the beginning of each rule, after zconftext and zconfleng\n * have been set up.\n */\n#ifndef YY_USER_ACTION\n#define YY_USER_ACTION\n#endif\n\n/* Code executed at the end of each rule. */\n#ifndef YY_BREAK\n#define YY_BREAK break;\n#endif\n\n#define YY_RULE_SETUP \\\n\tYY_USER_ACTION\n\n/** The main scanner function which does all the work.\n */\nYY_DECL\n{\n\tregister yy_state_type yy_current_state;\n\tregister char *yy_cp, *yy_bp;\n\tregister int yy_act;\n    \n\tint str = 0;\n\tint ts, i;\n\n\tif ( !(yy_init) )\n\t\t{\n\t\t(yy_init) = 1;\n\n#ifdef YY_USER_INIT\n\t\tYY_USER_INIT;\n#endif\n\n\t\tif ( ! (yy_start) )\n\t\t\t(yy_start) = 1;\t/* first start state */\n\n\t\tif ( ! zconfin )\n\t\t\tzconfin = stdin;\n\n\t\tif ( ! zconfout )\n\t\t\tzconfout = stdout;\n\n\t\tif ( ! YY_CURRENT_BUFFER ) {\n\t\t\tzconfensure_buffer_stack ();\n\t\t\tYY_CURRENT_BUFFER_LVALUE =\n\t\t\t\tzconf_create_buffer(zconfin,YY_BUF_SIZE );\n\t\t}\n\n\t\tzconf_load_buffer_state( );\n\t\t}\n\n\twhile ( 1 )\t\t/* loops until end-of-file is reached */\n\t\t{\n\t\tyy_cp = (yy_c_buf_p);\n\n\t\t/* Support of zconftext. */\n\t\t*yy_cp = (yy_hold_char);\n\n\t\t/* yy_bp points to the position in yy_ch_buf of the start of\n\t\t * the current run.\n\t\t */\n\t\tyy_bp = yy_cp;\n\n\t\tyy_current_state = (yy_start);\nyy_match:\n\t\twhile ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)]  ]) > 0 )\n\t\t\t++yy_cp;\n\n\t\tyy_current_state = -yy_current_state;\n\nyy_find_action:\n\t\tyy_act = yy_accept[yy_current_state];\n\n\t\tYY_DO_BEFORE_ACTION;\n\ndo_action:\t/* This label is used only to access EOF actions. */\n\n\t\tswitch ( yy_act )\n\t{ /* beginning of action switch */\ncase 1:\n/* rule 1 can match eol */\ncase 2:\n/* rule 2 can match eol */\nYY_RULE_SETUP\n{\n\tcurrent_file->lineno++;\n\treturn T_EOL;\n}\n\tYY_BREAK\ncase 3:\nYY_RULE_SETUP\n\n\tYY_BREAK\ncase 4:\nYY_RULE_SETUP\n{\n\tBEGIN(COMMAND);\n}\n\tYY_BREAK\ncase 5:\nYY_RULE_SETUP\n{\n\tunput(zconftext[0]);\n\tBEGIN(COMMAND);\n}\n\tYY_BREAK\n\ncase 6:\nYY_RULE_SETUP\n{\n\t\tconst struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);\n\t\tBEGIN(PARAM);\n\t\tcurrent_pos.file = current_file;\n\t\tcurrent_pos.lineno = current_file->lineno;\n\t\tif (id && id->flags & TF_COMMAND) {\n\t\t\tzconflval.id = id;\n\t\t\treturn id->token;\n\t\t}\n\t\talloc_string(zconftext, zconfleng);\n\t\tzconflval.string = text;\n\t\treturn T_WORD;\n\t}\n\tYY_BREAK\ncase 7:\nYY_RULE_SETUP\n\n\tYY_BREAK\ncase 8:\n/* rule 8 can match eol */\nYY_RULE_SETUP\n{\n\t\tBEGIN(INITIAL);\n\t\tcurrent_file->lineno++;\n\t\treturn T_EOL;\n\t}\n\tYY_BREAK\n\ncase 9:\nYY_RULE_SETUP\nreturn T_AND;\n\tYY_BREAK\ncase 10:\nYY_RULE_SETUP\nreturn T_OR;\n\tYY_BREAK\ncase 11:\nYY_RULE_SETUP\nreturn T_OPEN_PAREN;\n\tYY_BREAK\ncase 12:\nYY_RULE_SETUP\nreturn T_CLOSE_PAREN;\n\tYY_BREAK\ncase 13:\nYY_RULE_SETUP\nreturn T_NOT;\n\tYY_BREAK\ncase 14:\nYY_RULE_SETUP\nreturn T_EQUAL;\n\tYY_BREAK\ncase 15:\nYY_RULE_SETUP\nreturn T_UNEQUAL;\n\tYY_BREAK\ncase 16:\nYY_RULE_SETUP\n{\n\t\tstr = zconftext[0];\n\t\tnew_string();\n\t\tBEGIN(STRING);\n\t}\n\tYY_BREAK\ncase 17:\n/* rule 17 can match eol */\nYY_RULE_SETUP\nBEGIN(INITIAL); current_file->lineno++; return T_EOL;\n\tYY_BREAK\ncase 18:\nYY_RULE_SETUP\n/* ignore */\n\tYY_BREAK\ncase 19:\nYY_RULE_SETUP\n{\n\t\tconst struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);\n\t\tif (id && id->flags & TF_PARAM) {\n\t\t\tzconflval.id = id;\n\t\t\treturn id->token;\n\t\t}\n\t\talloc_string(zconftext, zconfleng);\n\t\tzconflval.string = text;\n\t\treturn T_WORD;\n\t}\n\tYY_BREAK\ncase 20:\nYY_RULE_SETUP\n/* comment */\n\tYY_BREAK\ncase 21:\n/* rule 21 can match eol */\nYY_RULE_SETUP\ncurrent_file->lineno++;\n\tYY_BREAK\ncase 22:\nYY_RULE_SETUP\n\n\tYY_BREAK\ncase YY_STATE_EOF(PARAM):\n{\n\t\tBEGIN(INITIAL);\n\t}\n\tYY_BREAK\n\ncase 23:\n/* rule 23 can match eol */\n*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */\n(yy_c_buf_p) = yy_cp -= 1;\nYY_DO_BEFORE_ACTION; /* set up zconftext again */\nYY_RULE_SETUP\n{\n\t\tappend_string(zconftext, zconfleng);\n\t\tzconflval.string = text;\n\t\treturn T_WORD_QUOTE;\n\t}\n\tYY_BREAK\ncase 24:\nYY_RULE_SETUP\n{\n\t\tappend_string(zconftext, zconfleng);\n\t}\n\tYY_BREAK\ncase 25:\n/* rule 25 can match eol */\n*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */\n(yy_c_buf_p) = yy_cp -= 1;\nYY_DO_BEFORE_ACTION; /* set up zconftext again */\nYY_RULE_SETUP\n{\n\t\tappend_string(zconftext + 1, zconfleng - 1);\n\t\tzconflval.string = text;\n\t\treturn T_WORD_QUOTE;\n\t}\n\tYY_BREAK\ncase 26:\nYY_RULE_SETUP\n{\n\t\tappend_string(zconftext + 1, zconfleng - 1);\n\t}\n\tYY_BREAK\ncase 27:\nYY_RULE_SETUP\n{\n\t\tif (str == zconftext[0]) {\n\t\t\tBEGIN(PARAM);\n\t\t\tzconflval.string = text;\n\t\t\treturn T_WORD_QUOTE;\n\t\t} else\n\t\t\tappend_string(zconftext, 1);\n\t}\n\tYY_BREAK\ncase 28:\n/* rule 28 can match eol */\nYY_RULE_SETUP\n{\n\t\tprintf(\"%s:%d:warning: multi-line strings not supported\\n\", zconf_curname(), zconf_lineno());\n\t\tcurrent_file->lineno++;\n\t\tBEGIN(INITIAL);\n\t\treturn T_EOL;\n\t}\n\tYY_BREAK\ncase YY_STATE_EOF(STRING):\n{\n\t\tBEGIN(INITIAL);\n\t}\n\tYY_BREAK\n\ncase 29:\nYY_RULE_SETUP\n{\n\t\tts = 0;\n\t\tfor (i = 0; i < zconfleng; i++) {\n\t\t\tif (zconftext[i] == '\\t')\n\t\t\t\tts = (ts & ~7) + 8;\n\t\t\telse\n\t\t\t\tts++;\n\t\t}\n\t\tlast_ts = ts;\n\t\tif (first_ts) {\n\t\t\tif (ts < first_ts) {\n\t\t\t\tzconf_endhelp();\n\t\t\t\treturn T_HELPTEXT;\n\t\t\t}\n\t\t\tts -= first_ts;\n\t\t\twhile (ts > 8) {\n\t\t\t\tappend_string(\"        \", 8);\n\t\t\t\tts -= 8;\n\t\t\t}\n\t\t\tappend_string(\"        \", ts);\n\t\t}\n\t}\n\tYY_BREAK\ncase 30:\n/* rule 30 can match eol */\n*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */\n(yy_c_buf_p) = yy_cp -= 1;\nYY_DO_BEFORE_ACTION; /* set up zconftext again */\nYY_RULE_SETUP\n{\n\t\tcurrent_file->lineno++;\n\t\tzconf_endhelp();\n\t\treturn T_HELPTEXT;\n\t}\n\tYY_BREAK\ncase 31:\n/* rule 31 can match eol */\nYY_RULE_SETUP\n{\n\t\tcurrent_file->lineno++;\n\t\tappend_string(\"\\n\", 1);\n\t}\n\tYY_BREAK\ncase 32:\nYY_RULE_SETUP\n{\n\t\twhile (zconfleng) {\n\t\t\tif ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\\t'))\n\t\t\t\tbreak;\n\t\t\tzconfleng--;\n\t\t}\n\t\tappend_string(zconftext, zconfleng);\n\t\tif (!first_ts)\n\t\t\tfirst_ts = last_ts;\n\t}\n\tYY_BREAK\ncase YY_STATE_EOF(HELP):\n{\n\t\tzconf_endhelp();\n\t\treturn T_HELPTEXT;\n\t}\n\tYY_BREAK\n\ncase YY_STATE_EOF(INITIAL):\ncase YY_STATE_EOF(COMMAND):\n{\n\tif (current_file) {\n\t\tzconf_endfile();\n\t\treturn T_EOL;\n\t}\n\tfclose(zconfin);\n\tyyterminate();\n}\n\tYY_BREAK\ncase 33:\nYY_RULE_SETUP\nYY_FATAL_ERROR( \"flex scanner jammed\" );\n\tYY_BREAK\n\n\tcase YY_END_OF_BUFFER:\n\t\t{\n\t\t/* Amount of text matched not including the EOB char. */\n\t\tint yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;\n\n\t\t/* Undo the effects of YY_DO_BEFORE_ACTION. */\n\t\t*yy_cp = (yy_hold_char);\n\t\tYY_RESTORE_YY_MORE_OFFSET\n\n\t\tif ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )\n\t\t\t{\n\t\t\t/* We're scanning a new file or input source.  It's\n\t\t\t * possible that this happened because the user\n\t\t\t * just pointed zconfin at a new source and called\n\t\t\t * zconflex().  If so, then we have to assure\n\t\t\t * consistency between YY_CURRENT_BUFFER and our\n\t\t\t * globals.  Here is the right place to do so, because\n\t\t\t * this is the first action (other than possibly a\n\t\t\t * back-up) that will match for the new input source.\n\t\t\t */\n\t\t\t(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;\n\t\t\t}\n\n\t\t/* Note that here we test for yy_c_buf_p \"<=\" to the position\n\t\t * of the first EOB in the buffer, since yy_c_buf_p will\n\t\t * already have been incremented past the NUL character\n\t\t * (since all states make transitions on EOB to the\n\t\t * end-of-buffer state).  Contrast this with the test\n\t\t * in input().\n\t\t */\n\t\tif ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )\n\t\t\t{ /* This was really a NUL. */\n\t\t\tyy_state_type yy_next_state;\n\n\t\t\t(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;\n\n\t\t\tyy_current_state = yy_get_previous_state(  );\n\n\t\t\t/* Okay, we're now positioned to make the NUL\n\t\t\t * transition.  We couldn't have\n\t\t\t * yy_get_previous_state() go ahead and do it\n\t\t\t * for us because it doesn't know how to deal\n\t\t\t * with the possibility of jamming (and we don't\n\t\t\t * want to build jamming into it because then it\n\t\t\t * will run more slowly).\n\t\t\t */\n\n\t\t\tyy_next_state = yy_try_NUL_trans( yy_current_state );\n\n\t\t\tyy_bp = (yytext_ptr) + YY_MORE_ADJ;\n\n\t\t\tif ( yy_next_state )\n\t\t\t\t{\n\t\t\t\t/* Consume the NUL. */\n\t\t\t\tyy_cp = ++(yy_c_buf_p);\n\t\t\t\tyy_current_state = yy_next_state;\n\t\t\t\tgoto yy_match;\n\t\t\t\t}\n\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tyy_cp = (yy_c_buf_p);\n\t\t\t\tgoto yy_find_action;\n\t\t\t\t}\n\t\t\t}\n\n\t\telse switch ( yy_get_next_buffer(  ) )\n\t\t\t{\n\t\t\tcase EOB_ACT_END_OF_FILE:\n\t\t\t\t{\n\t\t\t\t(yy_did_buffer_switch_on_eof) = 0;\n\n\t\t\t\tif ( zconfwrap( ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* Note: because we've taken care in\n\t\t\t\t\t * yy_get_next_buffer() to have set up\n\t\t\t\t\t * zconftext, we can now set up\n\t\t\t\t\t * yy_c_buf_p so that if some total\n\t\t\t\t\t * hoser (like flex itself) wants to\n\t\t\t\t\t * call the scanner after we return the\n\t\t\t\t\t * YY_NULL, it'll still work - another\n\t\t\t\t\t * YY_NULL will get returned.\n\t\t\t\t\t */\n\t\t\t\t\t(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;\n\n\t\t\t\t\tyy_act = YY_STATE_EOF(YY_START);\n\t\t\t\t\tgoto do_action;\n\t\t\t\t\t}\n\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif ( ! (yy_did_buffer_switch_on_eof) )\n\t\t\t\t\t\tYY_NEW_FILE;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase EOB_ACT_CONTINUE_SCAN:\n\t\t\t\t(yy_c_buf_p) =\n\t\t\t\t\t(yytext_ptr) + yy_amount_of_matched_text;\n\n\t\t\t\tyy_current_state = yy_get_previous_state(  );\n\n\t\t\t\tyy_cp = (yy_c_buf_p);\n\t\t\t\tyy_bp = (yytext_ptr) + YY_MORE_ADJ;\n\t\t\t\tgoto yy_match;\n\n\t\t\tcase EOB_ACT_LAST_MATCH:\n\t\t\t\t(yy_c_buf_p) =\n\t\t\t\t&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];\n\n\t\t\t\tyy_current_state = yy_get_previous_state(  );\n\n\t\t\t\tyy_cp = (yy_c_buf_p);\n\t\t\t\tyy_bp = (yytext_ptr) + YY_MORE_ADJ;\n\t\t\t\tgoto yy_find_action;\n\t\t\t}\n\t\tbreak;\n\t\t}\n\n\tdefault:\n\t\tYY_FATAL_ERROR(\n\t\t\t\"fatal flex scanner internal error--no action found\" );\n\t} /* end of action switch */\n\t\t} /* end of scanning one token */\n} /* end of zconflex */\n\n/* yy_get_next_buffer - try to read in a new buffer\n *\n * Returns a code representing an action:\n *\tEOB_ACT_LAST_MATCH -\n *\tEOB_ACT_CONTINUE_SCAN - continue scanning from current position\n *\tEOB_ACT_END_OF_FILE - end of file\n */\nstatic int yy_get_next_buffer (void)\n{\n    \tregister char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;\n\tregister char *source = (yytext_ptr);\n\tregister int number_to_move, i;\n\tint ret_val;\n\n\tif ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )\n\t\tYY_FATAL_ERROR(\n\t\t\"fatal flex scanner internal error--end of buffer missed\" );\n\n\tif ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )\n\t\t{ /* Don't try to fill the buffer, so this is an EOF. */\n\t\tif ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )\n\t\t\t{\n\t\t\t/* We matched a single character, the EOB, so\n\t\t\t * treat this as a final EOF.\n\t\t\t */\n\t\t\treturn EOB_ACT_END_OF_FILE;\n\t\t\t}\n\n\t\telse\n\t\t\t{\n\t\t\t/* We matched some text prior to the EOB, first\n\t\t\t * process it.\n\t\t\t */\n\t\t\treturn EOB_ACT_LAST_MATCH;\n\t\t\t}\n\t\t}\n\n\t/* Try to read more data. */\n\n\t/* First move last chars to start of buffer. */\n\tnumber_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;\n\n\tfor ( i = 0; i < number_to_move; ++i )\n\t\t*(dest++) = *(source++);\n\n\tif ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )\n\t\t/* don't do the read, it's not guaranteed to return an EOF,\n\t\t * just force an EOF\n\t\t */\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;\n\n\telse\n\t\t{\n\t\t\tint num_to_read =\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;\n\n\t\twhile ( num_to_read <= 0 )\n\t\t\t{ /* Not enough room in the buffer - grow it. */\n\n\t\t\t/* just a shorter name for the current buffer */\n\t\t\tYY_BUFFER_STATE b = YY_CURRENT_BUFFER;\n\n\t\t\tint yy_c_buf_p_offset =\n\t\t\t\t(int) ((yy_c_buf_p) - b->yy_ch_buf);\n\n\t\t\tif ( b->yy_is_our_buffer )\n\t\t\t\t{\n\t\t\t\tint new_size = b->yy_buf_size * 2;\n\n\t\t\t\tif ( new_size <= 0 )\n\t\t\t\t\tb->yy_buf_size += b->yy_buf_size / 8;\n\t\t\t\telse\n\t\t\t\t\tb->yy_buf_size *= 2;\n\n\t\t\t\tb->yy_ch_buf = (char *)\n\t\t\t\t\t/* Include room in for 2 EOB chars. */\n\t\t\t\t\tzconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t/* Can't grow it, we don't own it. */\n\t\t\t\tb->yy_ch_buf = 0;\n\n\t\t\tif ( ! b->yy_ch_buf )\n\t\t\t\tYY_FATAL_ERROR(\n\t\t\t\t\"fatal error - scanner input buffer overflow\" );\n\n\t\t\t(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];\n\n\t\t\tnum_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -\n\t\t\t\t\t\tnumber_to_move - 1;\n\n\t\t\t}\n\n\t\tif ( num_to_read > YY_READ_BUF_SIZE )\n\t\t\tnum_to_read = YY_READ_BUF_SIZE;\n\n\t\t/* Read in more data. */\n\t\tYY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),\n\t\t\t(yy_n_chars), (size_t) num_to_read );\n\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);\n\t\t}\n\n\tif ( (yy_n_chars) == 0 )\n\t\t{\n\t\tif ( number_to_move == YY_MORE_ADJ )\n\t\t\t{\n\t\t\tret_val = EOB_ACT_END_OF_FILE;\n\t\t\tzconfrestart(zconfin  );\n\t\t\t}\n\n\t\telse\n\t\t\t{\n\t\t\tret_val = EOB_ACT_LAST_MATCH;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_buffer_status =\n\t\t\t\tYY_BUFFER_EOF_PENDING;\n\t\t\t}\n\t\t}\n\n\telse\n\t\tret_val = EOB_ACT_CONTINUE_SCAN;\n\n\tif ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {\n\t\t/* Extend the array by 50%, plus the number we really need. */\n\t\tyy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );\n\t\tif ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in yy_get_next_buffer()\" );\n\t}\n\n\t(yy_n_chars) += number_to_move;\n\tYY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;\n\tYY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;\n\n\t(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];\n\n\treturn ret_val;\n}\n\n/* yy_get_previous_state - get the state just before the EOB char was reached */\n\n    static yy_state_type yy_get_previous_state (void)\n{\n\tregister yy_state_type yy_current_state;\n\tregister char *yy_cp;\n    \n\tyy_current_state = (yy_start);\n\n\tfor ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )\n\t\t{\n\t\tyy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)];\n\t\t}\n\n\treturn yy_current_state;\n}\n\n/* yy_try_NUL_trans - try to make a transition on the NUL character\n *\n * synopsis\n *\tnext_state = yy_try_NUL_trans( current_state );\n */\n    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )\n{\n\tregister int yy_is_jam;\n    \n\tyy_current_state = yy_nxt[yy_current_state][1];\n\tyy_is_jam = (yy_current_state <= 0);\n\n\treturn yy_is_jam ? 0 : yy_current_state;\n}\n\n    static void yyunput (int c, register char * yy_bp )\n{\n\tregister char *yy_cp;\n    \n    yy_cp = (yy_c_buf_p);\n\n\t/* undo effects of setting up zconftext */\n\t*yy_cp = (yy_hold_char);\n\n\tif ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )\n\t\t{ /* need to shift things up to make room */\n\t\t/* +2 for EOB chars. */\n\t\tregister int number_to_move = (yy_n_chars) + 2;\n\t\tregister char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[\n\t\t\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];\n\t\tregister char *source =\n\t\t\t\t&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];\n\n\t\twhile ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )\n\t\t\t*--dest = *--source;\n\n\t\tyy_cp += (int) (dest - source);\n\t\tyy_bp += (int) (dest - source);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars =\n\t\t\t(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;\n\n\t\tif ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )\n\t\t\tYY_FATAL_ERROR( \"flex scanner push-back overflow\" );\n\t\t}\n\n\t*--yy_cp = (char) c;\n\n\t(yytext_ptr) = yy_bp;\n\t(yy_hold_char) = *yy_cp;\n\t(yy_c_buf_p) = yy_cp;\n}\n\n#ifndef YY_NO_INPUT\n#ifdef __cplusplus\n    static int yyinput (void)\n#else\n    static int input  (void)\n#endif\n\n{\n\tint c;\n    \n\t*(yy_c_buf_p) = (yy_hold_char);\n\n\tif ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )\n\t\t{\n\t\t/* yy_c_buf_p now points to the character we want to return.\n\t\t * If this occurs *before* the EOB characters, then it's a\n\t\t * valid NUL; if not, then we've hit the end of the buffer.\n\t\t */\n\t\tif ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )\n\t\t\t/* This was really a NUL. */\n\t\t\t*(yy_c_buf_p) = '\\0';\n\n\t\telse\n\t\t\t{ /* need more input */\n\t\t\tint offset = (yy_c_buf_p) - (yytext_ptr);\n\t\t\t++(yy_c_buf_p);\n\n\t\t\tswitch ( yy_get_next_buffer(  ) )\n\t\t\t\t{\n\t\t\t\tcase EOB_ACT_LAST_MATCH:\n\t\t\t\t\t/* This happens because yy_g_n_b()\n\t\t\t\t\t * sees that we've accumulated a\n\t\t\t\t\t * token and flags that we need to\n\t\t\t\t\t * try matching the token before\n\t\t\t\t\t * proceeding.  But for input(),\n\t\t\t\t\t * there's no matching to consider.\n\t\t\t\t\t * So convert the EOB_ACT_LAST_MATCH\n\t\t\t\t\t * to EOB_ACT_END_OF_FILE.\n\t\t\t\t\t */\n\n\t\t\t\t\t/* Reset buffer status. */\n\t\t\t\t\tzconfrestart(zconfin );\n\n\t\t\t\t\t/*FALLTHROUGH*/\n\n\t\t\t\tcase EOB_ACT_END_OF_FILE:\n\t\t\t\t\t{\n\t\t\t\t\tif ( zconfwrap( ) )\n\t\t\t\t\t\treturn EOF;\n\n\t\t\t\t\tif ( ! (yy_did_buffer_switch_on_eof) )\n\t\t\t\t\t\tYY_NEW_FILE;\n#ifdef __cplusplus\n\t\t\t\t\treturn yyinput();\n#else\n\t\t\t\t\treturn input();\n#endif\n\t\t\t\t\t}\n\n\t\t\t\tcase EOB_ACT_CONTINUE_SCAN:\n\t\t\t\t\t(yy_c_buf_p) = (yytext_ptr) + offset;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tc = *(unsigned char *) (yy_c_buf_p);\t/* cast for 8-bit char's */\n\t*(yy_c_buf_p) = '\\0';\t/* preserve zconftext */\n\t(yy_hold_char) = *++(yy_c_buf_p);\n\n\treturn c;\n}\n#endif\t/* ifndef YY_NO_INPUT */\n\n/** Immediately switch to a different input stream.\n * @param input_file A readable stream.\n * \n * @note This function does not reset the start condition to @c INITIAL .\n */\n    void zconfrestart  (FILE * input_file )\n{\n    \n\tif ( ! YY_CURRENT_BUFFER ){\n        zconfensure_buffer_stack ();\n\t\tYY_CURRENT_BUFFER_LVALUE =\n            zconf_create_buffer(zconfin,YY_BUF_SIZE );\n\t}\n\n\tzconf_init_buffer(YY_CURRENT_BUFFER,input_file );\n\tzconf_load_buffer_state( );\n}\n\n/** Switch to a different input buffer.\n * @param new_buffer The new input buffer.\n * \n */\n    void zconf_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )\n{\n    \n\t/* TODO. We should be able to replace this entire function body\n\t * with\n\t *\t\tzconfpop_buffer_state();\n\t *\t\tzconfpush_buffer_state(new_buffer);\n     */\n\tzconfensure_buffer_stack ();\n\tif ( YY_CURRENT_BUFFER == new_buffer )\n\t\treturn;\n\n\tif ( YY_CURRENT_BUFFER )\n\t\t{\n\t\t/* Flush out information for old buffer. */\n\t\t*(yy_c_buf_p) = (yy_hold_char);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);\n\t\t}\n\n\tYY_CURRENT_BUFFER_LVALUE = new_buffer;\n\tzconf_load_buffer_state( );\n\n\t/* We don't actually know whether we did this switch during\n\t * EOF (zconfwrap()) processing, but the only time this flag\n\t * is looked at is after zconfwrap() is called, so it's safe\n\t * to go ahead and always set it.\n\t */\n\t(yy_did_buffer_switch_on_eof) = 1;\n}\n\nstatic void zconf_load_buffer_state  (void)\n{\n    \t(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;\n\t(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;\n\tzconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;\n\t(yy_hold_char) = *(yy_c_buf_p);\n}\n\n/** Allocate and initialize an input buffer state.\n * @param file A readable stream.\n * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.\n * \n * @return the allocated buffer state.\n */\n    YY_BUFFER_STATE zconf_create_buffer  (FILE * file, int  size )\n{\n\tYY_BUFFER_STATE b;\n    \n\tb = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in zconf_create_buffer()\" );\n\n\tb->yy_buf_size = size;\n\n\t/* yy_ch_buf has to be 2 characters longer than the size given because\n\t * we need to put in 2 end-of-buffer characters.\n\t */\n\tb->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2  );\n\tif ( ! b->yy_ch_buf )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in zconf_create_buffer()\" );\n\n\tb->yy_is_our_buffer = 1;\n\n\tzconf_init_buffer(b,file );\n\n\treturn b;\n}\n\n/** Destroy the buffer.\n * @param b a buffer created with zconf_create_buffer()\n * \n */\n    void zconf_delete_buffer (YY_BUFFER_STATE  b )\n{\n    \n\tif ( ! b )\n\t\treturn;\n\n\tif ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */\n\t\tYY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;\n\n\tif ( b->yy_is_our_buffer )\n\t\tzconffree((void *) b->yy_ch_buf  );\n\n\tzconffree((void *) b  );\n}\n\n/* Initializes or reinitializes a buffer.\n * This function is sometimes called more than once on the same buffer,\n * such as during a zconfrestart() or at EOF.\n */\n    static void zconf_init_buffer  (YY_BUFFER_STATE  b, FILE * file )\n\n{\n\tint oerrno = errno;\n    \n\tzconf_flush_buffer(b );\n\n\tb->yy_input_file = file;\n\tb->yy_fill_buffer = 1;\n\n    /* If b is the current buffer, then zconf_init_buffer was _probably_\n     * called from zconfrestart() or through yy_get_next_buffer.\n     * In that case, we don't want to reset the lineno or column.\n     */\n    if (b != YY_CURRENT_BUFFER){\n        b->yy_bs_lineno = 1;\n        b->yy_bs_column = 0;\n    }\n\n        b->yy_is_interactive = 0;\n    \n\terrno = oerrno;\n}\n\n/** Discard all buffered characters. On the next scan, YY_INPUT will be called.\n * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.\n * \n */\n    void zconf_flush_buffer (YY_BUFFER_STATE  b )\n{\n    \tif ( ! b )\n\t\treturn;\n\n\tb->yy_n_chars = 0;\n\n\t/* We always need two end-of-buffer characters.  The first causes\n\t * a transition to the end-of-buffer state.  The second causes\n\t * a jam in that state.\n\t */\n\tb->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;\n\tb->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;\n\n\tb->yy_buf_pos = &b->yy_ch_buf[0];\n\n\tb->yy_at_bol = 1;\n\tb->yy_buffer_status = YY_BUFFER_NEW;\n\n\tif ( b == YY_CURRENT_BUFFER )\n\t\tzconf_load_buffer_state( );\n}\n\n/** Pushes the new state onto the stack. The new state becomes\n *  the current state. This function will allocate the stack\n *  if necessary.\n *  @param new_buffer The new state.\n *  \n */\nvoid zconfpush_buffer_state (YY_BUFFER_STATE new_buffer )\n{\n    \tif (new_buffer == NULL)\n\t\treturn;\n\n\tzconfensure_buffer_stack();\n\n\t/* This block is copied from zconf_switch_to_buffer. */\n\tif ( YY_CURRENT_BUFFER )\n\t\t{\n\t\t/* Flush out information for old buffer. */\n\t\t*(yy_c_buf_p) = (yy_hold_char);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);\n\t\t}\n\n\t/* Only push if top exists. Otherwise, replace top. */\n\tif (YY_CURRENT_BUFFER)\n\t\t(yy_buffer_stack_top)++;\n\tYY_CURRENT_BUFFER_LVALUE = new_buffer;\n\n\t/* copied from zconf_switch_to_buffer. */\n\tzconf_load_buffer_state( );\n\t(yy_did_buffer_switch_on_eof) = 1;\n}\n\n/** Removes and deletes the top of the stack, if present.\n *  The next element becomes the new top.\n *  \n */\nvoid zconfpop_buffer_state (void)\n{\n    \tif (!YY_CURRENT_BUFFER)\n\t\treturn;\n\n\tzconf_delete_buffer(YY_CURRENT_BUFFER );\n\tYY_CURRENT_BUFFER_LVALUE = NULL;\n\tif ((yy_buffer_stack_top) > 0)\n\t\t--(yy_buffer_stack_top);\n\n\tif (YY_CURRENT_BUFFER) {\n\t\tzconf_load_buffer_state( );\n\t\t(yy_did_buffer_switch_on_eof) = 1;\n\t}\n}\n\n/* Allocates the stack if it does not exist.\n *  Guarantees space for at least one push.\n */\nstatic void zconfensure_buffer_stack (void)\n{\n\tint num_to_alloc;\n    \n\tif (!(yy_buffer_stack)) {\n\n\t\t/* First allocation is just for 2 elements, since we don't know if this\n\t\t * scanner will even need a stack. We use 2 instead of 1 to avoid an\n\t\t * immediate realloc on the next call.\n         */\n\t\tnum_to_alloc = 1;\n\t\t(yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc\n\t\t\t\t\t\t\t\t(num_to_alloc * sizeof(struct yy_buffer_state*)\n\t\t\t\t\t\t\t\t);\n\t\tif ( ! (yy_buffer_stack) )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in zconfensure_buffer_stack()\" );\n\t\t\t\t\t\t\t\t  \n\t\tmemset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));\n\t\t\t\t\n\t\t(yy_buffer_stack_max) = num_to_alloc;\n\t\t(yy_buffer_stack_top) = 0;\n\t\treturn;\n\t}\n\n\tif ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){\n\n\t\t/* Increase the buffer to prepare for a possible push. */\n\t\tint grow_size = 8 /* arbitrary grow size */;\n\n\t\tnum_to_alloc = (yy_buffer_stack_max) + grow_size;\n\t\t(yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc\n\t\t\t\t\t\t\t\t((yy_buffer_stack),\n\t\t\t\t\t\t\t\tnum_to_alloc * sizeof(struct yy_buffer_state*)\n\t\t\t\t\t\t\t\t);\n\t\tif ( ! (yy_buffer_stack) )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in zconfensure_buffer_stack()\" );\n\n\t\t/* zero only the new slots.*/\n\t\tmemset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));\n\t\t(yy_buffer_stack_max) = num_to_alloc;\n\t}\n}\n\n/** Setup the input buffer state to scan directly from a user-specified character buffer.\n * @param base the character buffer\n * @param size the size in bytes of the character buffer\n * \n * @return the newly allocated buffer state object. \n */\nYY_BUFFER_STATE zconf_scan_buffer  (char * base, yy_size_t  size )\n{\n\tYY_BUFFER_STATE b;\n    \n\tif ( size < 2 ||\n\t     base[size-2] != YY_END_OF_BUFFER_CHAR ||\n\t     base[size-1] != YY_END_OF_BUFFER_CHAR )\n\t\t/* They forgot to leave room for the EOB's. */\n\t\treturn 0;\n\n\tb = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state )  );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in zconf_scan_buffer()\" );\n\n\tb->yy_buf_size = size - 2;\t/* \"- 2\" to take care of EOB's */\n\tb->yy_buf_pos = b->yy_ch_buf = base;\n\tb->yy_is_our_buffer = 0;\n\tb->yy_input_file = 0;\n\tb->yy_n_chars = b->yy_buf_size;\n\tb->yy_is_interactive = 0;\n\tb->yy_at_bol = 1;\n\tb->yy_fill_buffer = 0;\n\tb->yy_buffer_status = YY_BUFFER_NEW;\n\n\tzconf_switch_to_buffer(b  );\n\n\treturn b;\n}\n\n/** Setup the input buffer state to scan a string. The next call to zconflex() will\n * scan from a @e copy of @a str.\n * @param yystr a NUL-terminated string to scan\n * \n * @return the newly allocated buffer state object.\n * @note If you want to scan bytes that may contain NUL values, then use\n *       zconf_scan_bytes() instead.\n */\nYY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )\n{\n    \n\treturn zconf_scan_bytes(yystr,strlen(yystr) );\n}\n\n/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will\n * scan from a @e copy of @a bytes.\n * @param bytes the byte buffer to scan\n * @param len the number of bytes in the buffer pointed to by @a bytes.\n * \n * @return the newly allocated buffer state object.\n */\nYY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )\n{\n\tYY_BUFFER_STATE b;\n\tchar *buf;\n\tyy_size_t n;\n\tint i;\n    \n\t/* Get memory for full buffer, including space for trailing EOB's. */\n\tn = _yybytes_len + 2;\n\tbuf = (char *) zconfalloc(n  );\n\tif ( ! buf )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in zconf_scan_bytes()\" );\n\n\tfor ( i = 0; i < _yybytes_len; ++i )\n\t\tbuf[i] = yybytes[i];\n\n\tbuf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;\n\n\tb = zconf_scan_buffer(buf,n );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"bad buffer in zconf_scan_bytes()\" );\n\n\t/* It's okay to grow etc. this buffer, and we should throw it\n\t * away when we're done.\n\t */\n\tb->yy_is_our_buffer = 1;\n\n\treturn b;\n}\n\n#ifndef YY_EXIT_FAILURE\n#define YY_EXIT_FAILURE 2\n#endif\n\nstatic void yy_fatal_error (yyconst char* msg )\n{\n    \t(void) fprintf( stderr, \"%s\\n\", msg );\n\texit( YY_EXIT_FAILURE );\n}\n\n/* Redefine yyless() so it works in section 3 code. */\n\n#undef yyless\n#define yyless(n) \\\n\tdo \\\n\t\t{ \\\n\t\t/* Undo effects of setting up zconftext. */ \\\n        int yyless_macro_arg = (n); \\\n        YY_LESS_LINENO(yyless_macro_arg);\\\n\t\tzconftext[zconfleng] = (yy_hold_char); \\\n\t\t(yy_c_buf_p) = zconftext + yyless_macro_arg; \\\n\t\t(yy_hold_char) = *(yy_c_buf_p); \\\n\t\t*(yy_c_buf_p) = '\\0'; \\\n\t\tzconfleng = yyless_macro_arg; \\\n\t\t} \\\n\twhile ( 0 )\n\n/* Accessor  methods (get/set functions) to struct members. */\n\n/** Get the current line number.\n * \n */\nint zconfget_lineno  (void)\n{\n        \n    return zconflineno;\n}\n\n/** Get the input stream.\n * \n */\nFILE *zconfget_in  (void)\n{\n        return zconfin;\n}\n\n/** Get the output stream.\n * \n */\nFILE *zconfget_out  (void)\n{\n        return zconfout;\n}\n\n/** Get the length of the current token.\n * \n */\nint zconfget_leng  (void)\n{\n        return zconfleng;\n}\n\n/** Get the current token.\n * \n */\n\nchar *zconfget_text  (void)\n{\n        return zconftext;\n}\n\n/** Set the current line number.\n * @param line_number\n * \n */\nvoid zconfset_lineno (int  line_number )\n{\n    \n    zconflineno = line_number;\n}\n\n/** Set the input stream. This does not discard the current\n * input buffer.\n * @param in_str A readable stream.\n * \n * @see zconf_switch_to_buffer\n */\nvoid zconfset_in (FILE *  in_str )\n{\n        zconfin = in_str ;\n}\n\nvoid zconfset_out (FILE *  out_str )\n{\n        zconfout = out_str ;\n}\n\nint zconfget_debug  (void)\n{\n        return zconf_flex_debug;\n}\n\nvoid zconfset_debug (int  bdebug )\n{\n        zconf_flex_debug = bdebug ;\n}\n\nstatic int yy_init_globals (void)\n{\n        /* Initialization is the same as for the non-reentrant scanner.\n     * This function is called from zconflex_destroy(), so don't allocate here.\n     */\n\n    (yy_buffer_stack) = 0;\n    (yy_buffer_stack_top) = 0;\n    (yy_buffer_stack_max) = 0;\n    (yy_c_buf_p) = (char *) 0;\n    (yy_init) = 0;\n    (yy_start) = 0;\n\n/* Defined in main.c */\n#ifdef YY_STDINIT\n    zconfin = stdin;\n    zconfout = stdout;\n#else\n    zconfin = (FILE *) 0;\n    zconfout = (FILE *) 0;\n#endif\n\n    /* For future reference: Set errno on error, since we are called by\n     * zconflex_init()\n     */\n    return 0;\n}\n\n/* zconflex_destroy is for both reentrant and non-reentrant scanners. */\nint zconflex_destroy  (void)\n{\n    \n    /* Pop the buffer stack, destroying each element. */\n\twhile(YY_CURRENT_BUFFER){\n\t\tzconf_delete_buffer(YY_CURRENT_BUFFER  );\n\t\tYY_CURRENT_BUFFER_LVALUE = NULL;\n\t\tzconfpop_buffer_state();\n\t}\n\n\t/* Destroy the stack itself. */\n\tzconffree((yy_buffer_stack) );\n\t(yy_buffer_stack) = NULL;\n\n    /* Reset the globals. This is important in a non-reentrant scanner so the next time\n     * zconflex() is called, initialization will occur. */\n    yy_init_globals( );\n\n    return 0;\n}\n\n/*\n * Internal utility routines.\n */\n\n#ifndef yytext_ptr\nstatic void yy_flex_strncpy (char* s1, yyconst char * s2, int n )\n{\n\tregister int i;\n\tfor ( i = 0; i < n; ++i )\n\t\ts1[i] = s2[i];\n}\n#endif\n\n#ifdef YY_NEED_STRLEN\nstatic int yy_flex_strlen (yyconst char * s )\n{\n\tregister int n;\n\tfor ( n = 0; s[n]; ++n )\n\t\t;\n\n\treturn n;\n}\n#endif\n\nvoid *zconfalloc (yy_size_t  size )\n{\n\treturn (void *) malloc( size );\n}\n\nvoid *zconfrealloc  (void * ptr, yy_size_t  size )\n{\n\t/* The cast to (char *) in the following accommodates both\n\t * implementations that use char* generic pointers, and those\n\t * that use void* generic pointers.  It works with the latter\n\t * because both ANSI C and C++ allow castless assignment from\n\t * any pointer type to void*, and deal with argument conversions\n\t * as though doing an assignment.\n\t */\n\treturn (void *) realloc( (char *) ptr, size );\n}\n\nvoid zconffree (void * ptr )\n{\n\tfree( (char *) ptr );\t/* see zconfrealloc() for (char *) cast */\n}\n\n#define YYTABLES_NAME \"yytables\"\n\nvoid zconf_starthelp(void)\n{\n\tnew_string();\n\tlast_ts = first_ts = 0;\n\tBEGIN(HELP);\n}\n\nstatic void zconf_endhelp(void)\n{\n\tzconflval.string = text;\n\tBEGIN(INITIAL);\n}\n\n/*\n * Try to open specified file with following names:\n * ./name\n * $(srctree)/name\n * The latter is used when srctree is separate from objtree\n * when compiling the kernel.\n * Return NULL if file is not found.\n */\nFILE *zconf_fopen(const char *name)\n{\n\tchar *env, fullname[PATH_MAX+1];\n\tFILE *f;\n\n\tf = fopen(name, \"r\");\n\tif (!f && name != NULL && name[0] != '/') {\n\t\tenv = getenv(SRCTREE);\n\t\tif (env) {\n\t\t\tsprintf(fullname, \"%s/%s\", env, name);\n\t\t\tf = fopen(fullname, \"r\");\n\t\t}\n\t}\n\treturn f;\n}\n\nvoid zconf_initscan(const char *name)\n{\n\tzconfin = zconf_fopen(name);\n\tif (!zconfin) {\n\t\tprintf(\"can't find file %s\\n\", name);\n\t\texit(1);\n\t}\n\n\tcurrent_buf = xmalloc(sizeof(*current_buf));\n\tmemset(current_buf, 0, sizeof(*current_buf));\n\n\tcurrent_file = file_lookup(name);\n\tcurrent_file->lineno = 1;\n}\n\nvoid zconf_nextfile(const char *name)\n{\n\tstruct file *iter;\n\tstruct file *file = file_lookup(name);\n\tstruct buffer *buf = xmalloc(sizeof(*buf));\n\tmemset(buf, 0, sizeof(*buf));\n\n\tcurrent_buf->state = YY_CURRENT_BUFFER;\n\tzconfin = zconf_fopen(file->name);\n\tif (!zconfin) {\n\t\tprintf(\"%s:%d: can't open file \\\"%s\\\"\\n\",\n\t\t    zconf_curname(), zconf_lineno(), file->name);\n\t\texit(1);\n\t}\n\tzconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));\n\tbuf->parent = current_buf;\n\tcurrent_buf = buf;\n\n\tfor (iter = current_file->parent; iter; iter = iter->parent ) {\n\t\tif (!strcmp(current_file->name,iter->name) ) {\n\t\t\tprintf(\"%s:%d: recursive inclusion detected. \"\n\t\t\t       \"Inclusion path:\\n  current file : '%s'\\n\",\n\t\t\t       zconf_curname(), zconf_lineno(),\n\t\t\t       zconf_curname());\n\t\t\titer = current_file->parent;\n\t\t\twhile (iter && \\\n\t\t\t       strcmp(iter->name,current_file->name)) {\n\t\t\t\tprintf(\"  included from: '%s:%d'\\n\",\n\t\t\t\t       iter->name, iter->lineno-1);\n\t\t\t\titer = iter->parent;\n\t\t\t}\n\t\t\tif (iter)\n\t\t\t\tprintf(\"  included from: '%s:%d'\\n\",\n\t\t\t\t       iter->name, iter->lineno+1);\n\t\t\texit(1);\n\t\t}\n\t}\n\tfile->lineno = 1;\n\tfile->parent = current_file;\n\tcurrent_file = file;\n}\n\nstatic void zconf_endfile(void)\n{\n\tstruct buffer *parent;\n\n\tcurrent_file = current_file->parent;\n\n\tparent = current_buf->parent;\n\tif (parent) {\n\t\tfclose(zconfin);\n\t\tzconf_delete_buffer(YY_CURRENT_BUFFER);\n\t\tzconf_switch_to_buffer(parent->state);\n\t}\n\tfree(current_buf);\n\tcurrent_buf = parent;\n}\n\nint zconf_lineno(void)\n{\n\treturn current_pos.lineno;\n}\n\nconst char *zconf_curname(void)\n{\n\treturn current_pos.file ? current_pos.file->name : \"<none>\";\n}\n\n"
  },
  {
    "path": "kconfig/zconf.tab.c_shipped",
    "content": "/* A Bison parser, made by GNU Bison 2.5.  */\n\n/* Bison implementation for Yacc-like parsers in C\n   \n      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.\n   \n   This program is free software: you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation, either version 3 of the License, or\n   (at your option) any later version.\n   \n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n   \n   You should have received a copy of the GNU General Public License\n   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */\n\n/* As a special exception, you may create a larger work that contains\n   part or all of the Bison parser skeleton and distribute that work\n   under terms of your choice, so long as that work isn't itself a\n   parser generator using the skeleton or a modified version thereof\n   as a parser skeleton.  Alternatively, if you modify or redistribute\n   the parser skeleton itself, you may (at your option) remove this\n   special exception, which will cause the skeleton and the resulting\n   Bison output files to be licensed under the GNU General Public\n   License without this special exception.\n   \n   This special exception was added by the Free Software Foundation in\n   version 2.2 of Bison.  */\n\n/* C LALR(1) parser skeleton written by Richard Stallman, by\n   simplifying the original so-called \"semantic\" parser.  */\n\n/* All symbols defined below should begin with yy or YY, to avoid\n   infringing on user name space.  This should be done even for local\n   variables, as they might otherwise be expanded by user macros.\n   There are some unavoidable exceptions within include files to\n   define necessary library symbols; they are noted \"INFRINGES ON\n   USER NAME SPACE\" below.  */\n\n/* Identify Bison output.  */\n#define YYBISON 1\n\n/* Bison version.  */\n#define YYBISON_VERSION \"2.5\"\n\n/* Skeleton name.  */\n#define YYSKELETON_NAME \"yacc.c\"\n\n/* Pure parsers.  */\n#define YYPURE 0\n\n/* Push parsers.  */\n#define YYPUSH 0\n\n/* Pull parsers.  */\n#define YYPULL 1\n\n/* Using locations.  */\n#define YYLSP_NEEDED 0\n\n/* Substitute the variable and function names.  */\n#define yyparse         zconfparse\n#define yylex           zconflex\n#define yyerror         zconferror\n#define yylval          zconflval\n#define yychar          zconfchar\n#define yydebug         zconfdebug\n#define yynerrs         zconfnerrs\n\n\n/* Copy the first part of user declarations.  */\n\n\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdbool.h>\n\n#include \"lkc.h\"\n\n#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)\n\n#define PRINTD\t\t0x0001\n#define DEBUG_PARSE\t0x0002\n\nint cdebug = PRINTD;\n\nextern int zconflex(void);\nstatic void zconfprint(const char *err, ...);\nstatic void zconf_error(const char *err, ...);\nstatic void zconferror(const char *err);\nstatic bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);\n\nstruct symbol *symbol_hash[SYMBOL_HASHSIZE];\n\nstatic struct menu *current_menu, *current_entry;\n\n\n\n\n/* Enabling traces.  */\n#ifndef YYDEBUG\n# define YYDEBUG 1\n#endif\n\n/* Enabling verbose error messages.  */\n#ifdef YYERROR_VERBOSE\n# undef YYERROR_VERBOSE\n# define YYERROR_VERBOSE 1\n#else\n# define YYERROR_VERBOSE 0\n#endif\n\n/* Enabling the token table.  */\n#ifndef YYTOKEN_TABLE\n# define YYTOKEN_TABLE 0\n#endif\n\n\n/* Tokens.  */\n#ifndef YYTOKENTYPE\n# define YYTOKENTYPE\n   /* Put the tokens into the symbol table, so that GDB and other debuggers\n      know about them.  */\n   enum yytokentype {\n     T_MAINMENU = 258,\n     T_MENU = 259,\n     T_ENDMENU = 260,\n     T_SOURCE = 261,\n     T_CHOICE = 262,\n     T_ENDCHOICE = 263,\n     T_COMMENT = 264,\n     T_CONFIG = 265,\n     T_MENUCONFIG = 266,\n     T_HELP = 267,\n     T_HELPTEXT = 268,\n     T_IF = 269,\n     T_ENDIF = 270,\n     T_DEPENDS = 271,\n     T_OPTIONAL = 272,\n     T_PROMPT = 273,\n     T_TYPE = 274,\n     T_DEFAULT = 275,\n     T_SELECT = 276,\n     T_RANGE = 277,\n     T_VISIBLE = 278,\n     T_OPTION = 279,\n     T_ON = 280,\n     T_WORD = 281,\n     T_WORD_QUOTE = 282,\n     T_UNEQUAL = 283,\n     T_CLOSE_PAREN = 284,\n     T_OPEN_PAREN = 285,\n     T_EOL = 286,\n     T_OR = 287,\n     T_AND = 288,\n     T_EQUAL = 289,\n     T_NOT = 290\n   };\n#endif\n\n\n\n#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED\ntypedef union YYSTYPE\n{\n\n\n\tchar *string;\n\tstruct file *file;\n\tstruct symbol *symbol;\n\tstruct expr *expr;\n\tstruct menu *menu;\n\tconst struct kconf_id *id;\n\n\n\n} YYSTYPE;\n# define YYSTYPE_IS_TRIVIAL 1\n# define yystype YYSTYPE /* obsolescent; will be withdrawn */\n# define YYSTYPE_IS_DECLARED 1\n#endif\n\n\n/* Copy the second part of user declarations.  */\n\n\n/* Include zconf.hash.c here so it can see the token constants. */\n#include \"zconf.hash.c\"\n\n\n\n#ifdef short\n# undef short\n#endif\n\n#ifdef YYTYPE_UINT8\ntypedef YYTYPE_UINT8 yytype_uint8;\n#else\ntypedef unsigned char yytype_uint8;\n#endif\n\n#ifdef YYTYPE_INT8\ntypedef YYTYPE_INT8 yytype_int8;\n#elif (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\ntypedef signed char yytype_int8;\n#else\ntypedef short int yytype_int8;\n#endif\n\n#ifdef YYTYPE_UINT16\ntypedef YYTYPE_UINT16 yytype_uint16;\n#else\ntypedef unsigned short int yytype_uint16;\n#endif\n\n#ifdef YYTYPE_INT16\ntypedef YYTYPE_INT16 yytype_int16;\n#else\ntypedef short int yytype_int16;\n#endif\n\n#ifndef YYSIZE_T\n# ifdef __SIZE_TYPE__\n#  define YYSIZE_T __SIZE_TYPE__\n# elif defined size_t\n#  define YYSIZE_T size_t\n# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\n#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */\n#  define YYSIZE_T size_t\n# else\n#  define YYSIZE_T unsigned int\n# endif\n#endif\n\n#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)\n\n#ifndef YY_\n# if defined YYENABLE_NLS && YYENABLE_NLS\n#  if ENABLE_NLS\n#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */\n#   define YY_(msgid) dgettext (\"bison-runtime\", msgid)\n#  endif\n# endif\n# ifndef YY_\n#  define YY_(msgid) msgid\n# endif\n#endif\n\n/* Suppress unused-variable warnings by \"using\" E.  */\n#if ! defined lint || defined __GNUC__\n# define YYUSE(e) ((void) (e))\n#else\n# define YYUSE(e) /* empty */\n#endif\n\n/* Identity function, used to suppress warnings about constant conditions.  */\n#ifndef lint\n# define YYID(n) (n)\n#else\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic int\nYYID (int yyi)\n#else\nstatic int\nYYID (yyi)\n    int yyi;\n#endif\n{\n  return yyi;\n}\n#endif\n\n#if ! defined yyoverflow || YYERROR_VERBOSE\n\n/* The parser invokes alloca or malloc; define the necessary symbols.  */\n\n# ifdef YYSTACK_USE_ALLOCA\n#  if YYSTACK_USE_ALLOCA\n#   ifdef __GNUC__\n#    define YYSTACK_ALLOC __builtin_alloca\n#   elif defined __BUILTIN_VA_ARG_INCR\n#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */\n#   elif defined _AIX\n#    define YYSTACK_ALLOC __alloca\n#   elif defined _MSC_VER\n#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */\n#    define alloca _alloca\n#   else\n#    define YYSTACK_ALLOC alloca\n#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\n#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */\n#     ifndef EXIT_SUCCESS\n#      define EXIT_SUCCESS 0\n#     endif\n#    endif\n#   endif\n#  endif\n# endif\n\n# ifdef YYSTACK_ALLOC\n   /* Pacify GCC's `empty if-body' warning.  */\n#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))\n#  ifndef YYSTACK_ALLOC_MAXIMUM\n    /* The OS might guarantee only one guard page at the bottom of the stack,\n       and a page size can be as small as 4096 bytes.  So we cannot safely\n       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number\n       to allow for a few compiler-allocated temporary stack slots.  */\n#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */\n#  endif\n# else\n#  define YYSTACK_ALLOC YYMALLOC\n#  define YYSTACK_FREE YYFREE\n#  ifndef YYSTACK_ALLOC_MAXIMUM\n#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM\n#  endif\n#  if (defined __cplusplus && ! defined EXIT_SUCCESS \\\n       && ! ((defined YYMALLOC || defined malloc) \\\n\t     && (defined YYFREE || defined free)))\n#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */\n#   ifndef EXIT_SUCCESS\n#    define EXIT_SUCCESS 0\n#   endif\n#  endif\n#  ifndef YYMALLOC\n#   define YYMALLOC malloc\n#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nvoid *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */\n#   endif\n#  endif\n#  ifndef YYFREE\n#   define YYFREE free\n#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nvoid free (void *); /* INFRINGES ON USER NAME SPACE */\n#   endif\n#  endif\n# endif\n#endif /* ! defined yyoverflow || YYERROR_VERBOSE */\n\n\n#if (! defined yyoverflow \\\n     && (! defined __cplusplus \\\n\t || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))\n\n/* A type that is properly aligned for any stack member.  */\nunion yyalloc\n{\n  yytype_int16 yyss_alloc;\n  YYSTYPE yyvs_alloc;\n};\n\n/* The size of the maximum gap between one aligned stack and the next.  */\n# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)\n\n/* The size of an array large to enough to hold all stacks, each with\n   N elements.  */\n# define YYSTACK_BYTES(N) \\\n     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \\\n      + YYSTACK_GAP_MAXIMUM)\n\n# define YYCOPY_NEEDED 1\n\n/* Relocate STACK from its old location to the new one.  The\n   local variables YYSIZE and YYSTACKSIZE give the old and new number of\n   elements in the stack, and YYPTR gives the new location of the\n   stack.  Advance YYPTR to a properly aligned location for the next\n   stack.  */\n# define YYSTACK_RELOCATE(Stack_alloc, Stack)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n      {\t\t\t\t\t\t\t\t\t\\\n\tYYSIZE_T yynewbytes;\t\t\t\t\t\t\\\n\tYYCOPY (&yyptr->Stack_alloc, Stack, yysize);\t\t\t\\\n\tStack = &yyptr->Stack_alloc;\t\t\t\t\t\\\n\tyynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \\\n\tyyptr += yynewbytes / sizeof (*yyptr);\t\t\t\t\\\n      }\t\t\t\t\t\t\t\t\t\\\n    while (YYID (0))\n\n#endif\n\n#if defined YYCOPY_NEEDED && YYCOPY_NEEDED\n/* Copy COUNT objects from FROM to TO.  The source and destination do\n   not overlap.  */\n# ifndef YYCOPY\n#  if defined __GNUC__ && 1 < __GNUC__\n#   define YYCOPY(To, From, Count) \\\n      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))\n#  else\n#   define YYCOPY(To, From, Count)\t\t\\\n      do\t\t\t\t\t\\\n\t{\t\t\t\t\t\\\n\t  YYSIZE_T yyi;\t\t\t\t\\\n\t  for (yyi = 0; yyi < (Count); yyi++)\t\\\n\t    (To)[yyi] = (From)[yyi];\t\t\\\n\t}\t\t\t\t\t\\\n      while (YYID (0))\n#  endif\n# endif\n#endif /* !YYCOPY_NEEDED */\n\n/* YYFINAL -- State number of the termination state.  */\n#define YYFINAL  11\n/* YYLAST -- Last index in YYTABLE.  */\n#define YYLAST   290\n\n/* YYNTOKENS -- Number of terminals.  */\n#define YYNTOKENS  36\n/* YYNNTS -- Number of nonterminals.  */\n#define YYNNTS  50\n/* YYNRULES -- Number of rules.  */\n#define YYNRULES  118\n/* YYNRULES -- Number of states.  */\n#define YYNSTATES  191\n\n/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */\n#define YYUNDEFTOK  2\n#define YYMAXUTOK   290\n\n#define YYTRANSLATE(YYX)\t\t\t\t\t\t\\\n  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)\n\n/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */\nstatic const yytype_uint8 yytranslate[] =\n{\n       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,\n       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,\n      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,\n      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,\n      35\n};\n\n#if YYDEBUG\n/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in\n   YYRHS.  */\nstatic const yytype_uint16 yyprhs[] =\n{\n       0,     0,     3,     6,     8,    11,    13,    14,    17,    20,\n      23,    26,    31,    36,    40,    42,    44,    46,    48,    50,\n      52,    54,    56,    58,    60,    62,    64,    66,    68,    72,\n      75,    79,    82,    86,    89,    90,    93,    96,    99,   102,\n     105,   108,   112,   117,   122,   127,   133,   137,   138,   142,\n     143,   146,   150,   153,   155,   159,   160,   163,   166,   169,\n     172,   175,   180,   184,   187,   192,   193,   196,   200,   202,\n     206,   207,   210,   213,   216,   220,   224,   228,   230,   234,\n     235,   238,   241,   244,   248,   252,   255,   258,   261,   262,\n     265,   268,   271,   276,   277,   280,   283,   286,   287,   290,\n     292,   294,   297,   300,   303,   305,   308,   309,   312,   314,\n     318,   322,   326,   329,   333,   337,   339,   341,   342\n};\n\n/* YYRHS -- A `-1'-separated list of the rules' RHS.  */\nstatic const yytype_int8 yyrhs[] =\n{\n      37,     0,    -1,    81,    38,    -1,    38,    -1,    63,    39,\n      -1,    39,    -1,    -1,    39,    41,    -1,    39,    55,    -1,\n      39,    67,    -1,    39,    80,    -1,    39,    26,     1,    31,\n      -1,    39,    40,     1,    31,    -1,    39,     1,    31,    -1,\n      16,    -1,    18,    -1,    19,    -1,    21,    -1,    17,    -1,\n      22,    -1,    20,    -1,    23,    -1,    31,    -1,    61,    -1,\n      71,    -1,    44,    -1,    46,    -1,    69,    -1,    26,     1,\n      31,    -1,     1,    31,    -1,    10,    26,    31,    -1,    43,\n      47,    -1,    11,    26,    31,    -1,    45,    47,    -1,    -1,\n      47,    48,    -1,    47,    49,    -1,    47,    75,    -1,    47,\n      73,    -1,    47,    42,    -1,    47,    31,    -1,    19,    78,\n      31,    -1,    18,    79,    82,    31,    -1,    20,    83,    82,\n      31,    -1,    21,    26,    82,    31,    -1,    22,    84,    84,\n      82,    31,    -1,    24,    50,    31,    -1,    -1,    50,    26,\n      51,    -1,    -1,    34,    79,    -1,     7,    85,    31,    -1,\n      52,    56,    -1,    80,    -1,    53,    58,    54,    -1,    -1,\n      56,    57,    -1,    56,    75,    -1,    56,    73,    -1,    56,\n      31,    -1,    56,    42,    -1,    18,    79,    82,    31,    -1,\n      19,    78,    31,    -1,    17,    31,    -1,    20,    26,    82,\n      31,    -1,    -1,    58,    41,    -1,    14,    83,    81,    -1,\n      80,    -1,    59,    62,    60,    -1,    -1,    62,    41,    -1,\n      62,    67,    -1,    62,    55,    -1,     3,    79,    81,    -1,\n       4,    79,    31,    -1,    64,    76,    74,    -1,    80,    -1,\n      65,    68,    66,    -1,    -1,    68,    41,    -1,    68,    67,\n      -1,    68,    55,    -1,     6,    79,    31,    -1,     9,    79,\n      31,    -1,    70,    74,    -1,    12,    31,    -1,    72,    13,\n      -1,    -1,    74,    75,    -1,    74,    31,    -1,    74,    42,\n      -1,    16,    25,    83,    31,    -1,    -1,    76,    77,    -1,\n      76,    31,    -1,    23,    82,    -1,    -1,    79,    82,    -1,\n      26,    -1,    27,    -1,     5,    31,    -1,     8,    31,    -1,\n      15,    31,    -1,    31,    -1,    81,    31,    -1,    -1,    14,\n      83,    -1,    84,    -1,    84,    34,    84,    -1,    84,    28,\n      84,    -1,    30,    83,    29,    -1,    35,    83,    -1,    83,\n      32,    83,    -1,    83,    33,    83,    -1,    26,    -1,    27,\n      -1,    -1,    26,    -1\n};\n\n/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */\nstatic const yytype_uint16 yyrline[] =\n{\n       0,   103,   103,   103,   105,   105,   107,   109,   110,   111,\n     112,   113,   114,   118,   122,   122,   122,   122,   122,   122,\n     122,   122,   126,   127,   128,   129,   130,   131,   135,   136,\n     142,   150,   156,   164,   174,   176,   177,   178,   179,   180,\n     181,   184,   192,   198,   208,   214,   220,   223,   225,   236,\n     237,   242,   251,   256,   264,   267,   269,   270,   271,   272,\n     273,   276,   282,   293,   299,   309,   311,   316,   324,   332,\n     335,   337,   338,   339,   344,   351,   358,   363,   371,   374,\n     376,   377,   378,   381,   389,   396,   403,   409,   416,   418,\n     419,   420,   423,   431,   433,   434,   437,   444,   446,   451,\n     452,   455,   456,   457,   461,   462,   465,   466,   469,   470,\n     471,   472,   473,   474,   475,   478,   479,   482,   483\n};\n#endif\n\n#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE\n/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.\n   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */\nstatic const char *const yytname[] =\n{\n  \"$end\", \"error\", \"$undefined\", \"T_MAINMENU\", \"T_MENU\", \"T_ENDMENU\",\n  \"T_SOURCE\", \"T_CHOICE\", \"T_ENDCHOICE\", \"T_COMMENT\", \"T_CONFIG\",\n  \"T_MENUCONFIG\", \"T_HELP\", \"T_HELPTEXT\", \"T_IF\", \"T_ENDIF\", \"T_DEPENDS\",\n  \"T_OPTIONAL\", \"T_PROMPT\", \"T_TYPE\", \"T_DEFAULT\", \"T_SELECT\", \"T_RANGE\",\n  \"T_VISIBLE\", \"T_OPTION\", \"T_ON\", \"T_WORD\", \"T_WORD_QUOTE\", \"T_UNEQUAL\",\n  \"T_CLOSE_PAREN\", \"T_OPEN_PAREN\", \"T_EOL\", \"T_OR\", \"T_AND\", \"T_EQUAL\",\n  \"T_NOT\", \"$accept\", \"input\", \"start\", \"stmt_list\", \"option_name\",\n  \"common_stmt\", \"option_error\", \"config_entry_start\", \"config_stmt\",\n  \"menuconfig_entry_start\", \"menuconfig_stmt\", \"config_option_list\",\n  \"config_option\", \"symbol_option\", \"symbol_option_list\",\n  \"symbol_option_arg\", \"choice\", \"choice_entry\", \"choice_end\",\n  \"choice_stmt\", \"choice_option_list\", \"choice_option\", \"choice_block\",\n  \"if_entry\", \"if_end\", \"if_stmt\", \"if_block\", \"mainmenu_stmt\", \"menu\",\n  \"menu_entry\", \"menu_end\", \"menu_stmt\", \"menu_block\", \"source_stmt\",\n  \"comment\", \"comment_stmt\", \"help_start\", \"help\", \"depends_list\",\n  \"depends\", \"visibility_list\", \"visible\", \"prompt_stmt_opt\", \"prompt\",\n  \"end\", \"nl\", \"if_expr\", \"expr\", \"symbol\", \"word_opt\", 0\n};\n#endif\n\n# ifdef YYPRINT\n/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to\n   token YYLEX-NUM.  */\nstatic const yytype_uint16 yytoknum[] =\n{\n       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,\n     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,\n     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,\n     285,   286,   287,   288,   289,   290\n};\n# endif\n\n/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */\nstatic const yytype_uint8 yyr1[] =\n{\n       0,    36,    37,    37,    38,    38,    39,    39,    39,    39,\n      39,    39,    39,    39,    40,    40,    40,    40,    40,    40,\n      40,    40,    41,    41,    41,    41,    41,    41,    42,    42,\n      43,    44,    45,    46,    47,    47,    47,    47,    47,    47,\n      47,    48,    48,    48,    48,    48,    49,    50,    50,    51,\n      51,    52,    53,    54,    55,    56,    56,    56,    56,    56,\n      56,    57,    57,    57,    57,    58,    58,    59,    60,    61,\n      62,    62,    62,    62,    63,    64,    65,    66,    67,    68,\n      68,    68,    68,    69,    70,    71,    72,    73,    74,    74,\n      74,    74,    75,    76,    76,    76,    77,    78,    78,    79,\n      79,    80,    80,    80,    81,    81,    82,    82,    83,    83,\n      83,    83,    83,    83,    83,    84,    84,    85,    85\n};\n\n/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */\nstatic const yytype_uint8 yyr2[] =\n{\n       0,     2,     2,     1,     2,     1,     0,     2,     2,     2,\n       2,     4,     4,     3,     1,     1,     1,     1,     1,     1,\n       1,     1,     1,     1,     1,     1,     1,     1,     3,     2,\n       3,     2,     3,     2,     0,     2,     2,     2,     2,     2,\n       2,     3,     4,     4,     4,     5,     3,     0,     3,     0,\n       2,     3,     2,     1,     3,     0,     2,     2,     2,     2,\n       2,     4,     3,     2,     4,     0,     2,     3,     1,     3,\n       0,     2,     2,     2,     3,     3,     3,     1,     3,     0,\n       2,     2,     2,     3,     3,     2,     2,     2,     0,     2,\n       2,     2,     4,     0,     2,     2,     2,     0,     2,     1,\n       1,     2,     2,     2,     1,     2,     0,     2,     1,     3,\n       3,     3,     2,     3,     3,     1,     1,     0,     1\n};\n\n/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.\n   Performed when YYTABLE doesn't specify something else to do.  Zero\n   means the default is an error.  */\nstatic const yytype_uint8 yydefact[] =\n{\n       6,     0,   104,     0,     3,     0,     6,     6,    99,   100,\n       0,     1,     0,     0,     0,     0,   117,     0,     0,     0,\n       0,     0,     0,    14,    18,    15,    16,    20,    17,    19,\n      21,     0,    22,     0,     7,    34,    25,    34,    26,    55,\n      65,     8,    70,    23,    93,    79,     9,    27,    88,    24,\n      10,     0,   105,     2,    74,    13,     0,   101,     0,   118,\n       0,   102,     0,     0,     0,   115,   116,     0,     0,     0,\n     108,   103,     0,     0,     0,     0,     0,     0,     0,    88,\n       0,     0,    75,    83,    51,    84,    30,    32,     0,   112,\n       0,     0,    67,     0,     0,    11,    12,     0,     0,     0,\n       0,    97,     0,     0,     0,    47,     0,    40,    39,    35,\n      36,     0,    38,    37,     0,     0,    97,     0,    59,    60,\n      56,    58,    57,    66,    54,    53,    71,    73,    69,    72,\n      68,   106,    95,     0,    94,    80,    82,    78,    81,    77,\n      90,    91,    89,   111,   113,   114,   110,   109,    29,    86,\n       0,   106,     0,   106,   106,   106,     0,     0,     0,    87,\n      63,   106,     0,   106,     0,    96,     0,     0,    41,    98,\n       0,     0,   106,    49,    46,    28,     0,    62,     0,   107,\n      92,    42,    43,    44,     0,     0,    48,    61,    64,    45,\n      50\n};\n\n/* YYDEFGOTO[NTERM-NUM].  */\nstatic const yytype_int16 yydefgoto[] =\n{\n      -1,     3,     4,     5,    33,    34,   108,    35,    36,    37,\n      38,    74,   109,   110,   157,   186,    39,    40,   124,    41,\n      76,   120,    77,    42,   128,    43,    78,     6,    44,    45,\n     137,    46,    80,    47,    48,    49,   111,   112,    81,   113,\n      79,   134,   152,   153,    50,     7,   165,    69,    70,    60\n};\n\n/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing\n   STATE-NUM.  */\n#define YYPACT_NINF -90\nstatic const yytype_int16 yypact[] =\n{\n       4,    42,   -90,    96,   -90,   111,   -90,    15,   -90,   -90,\n      75,   -90,    82,    42,   104,    42,   110,   107,    42,   115,\n     125,    -4,   121,   -90,   -90,   -90,   -90,   -90,   -90,   -90,\n     -90,   162,   -90,   163,   -90,   -90,   -90,   -90,   -90,   -90,\n     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,\n     -90,   139,   -90,   -90,   138,   -90,   142,   -90,   143,   -90,\n     152,   -90,   164,   167,   168,   -90,   -90,    -4,    -4,    77,\n     -18,   -90,   177,   185,    33,    71,   195,   247,   236,    -2,\n     236,   171,   -90,   -90,   -90,   -90,   -90,   -90,    41,   -90,\n      -4,    -4,   138,    97,    97,   -90,   -90,   186,   187,   194,\n      42,    42,    -4,   196,    97,   -90,   219,   -90,   -90,   -90,\n     -90,   210,   -90,   -90,   204,    42,    42,   199,   -90,   -90,\n     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,\n     -90,   222,   -90,   223,   -90,   -90,   -90,   -90,   -90,   -90,\n     -90,   -90,   -90,   -90,   215,   -90,   -90,   -90,   -90,   -90,\n      -4,   222,   228,   222,    -5,   222,    97,    35,   229,   -90,\n     -90,   222,   232,   222,    -4,   -90,   135,   233,   -90,   -90,\n     234,   235,   222,   240,   -90,   -90,   237,   -90,   239,   -13,\n     -90,   -90,   -90,   -90,   244,    42,   -90,   -90,   -90,   -90,\n     -90\n};\n\n/* YYPGOTO[NTERM-NUM].  */\nstatic const yytype_int16 yypgoto[] =\n{\n     -90,   -90,   269,   271,   -90,    23,   -70,   -90,   -90,   -90,\n     -90,   243,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -48,\n     -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,   -90,\n     -90,   -20,   -90,   -90,   -90,   -90,   -90,   206,   205,   -68,\n     -90,   -90,   169,    -1,    27,    -7,   118,   -66,   -89,   -90\n};\n\n/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If\n   positive, shift that token.  If negative, reduce the rule which\n   number is the opposite.  If YYTABLE_NINF, syntax error.  */\n#define YYTABLE_NINF -86\nstatic const yytype_int16 yytable[] =\n{\n      10,    88,    89,    54,   146,   147,   119,     1,   122,   164,\n      93,   141,    56,   142,    58,   156,    94,    62,     1,    90,\n      91,   131,    65,    66,   144,   145,    67,    90,    91,   132,\n     127,    68,   136,   -31,    97,     2,   154,   -31,   -31,   -31,\n     -31,   -31,   -31,   -31,   -31,    98,    52,   -31,   -31,    99,\n     -31,   100,   101,   102,   103,   104,   -31,   105,   129,   106,\n     138,   173,    92,   141,   107,   142,   174,   172,     8,     9,\n     143,   -33,    97,    90,    91,   -33,   -33,   -33,   -33,   -33,\n     -33,   -33,   -33,    98,   166,   -33,   -33,    99,   -33,   100,\n     101,   102,   103,   104,   -33,   105,    11,   106,   179,   151,\n     123,   126,   107,   135,   125,   130,     2,   139,     2,    90,\n      91,    -5,    12,    55,   161,    13,    14,    15,    16,    17,\n      18,    19,    20,    65,    66,    21,    22,    23,    24,    25,\n      26,    27,    28,    29,    30,    57,    59,    31,    61,    -4,\n      12,    63,    32,    13,    14,    15,    16,    17,    18,    19,\n      20,    64,    71,    21,    22,    23,    24,    25,    26,    27,\n      28,    29,    30,    72,    73,    31,   180,    90,    91,    52,\n      32,   -85,    97,    82,    83,   -85,   -85,   -85,   -85,   -85,\n     -85,   -85,   -85,    84,   190,   -85,   -85,    99,   -85,   -85,\n     -85,   -85,   -85,   -85,   -85,    85,    97,   106,    86,    87,\n     -52,   -52,   140,   -52,   -52,   -52,   -52,    98,    95,   -52,\n     -52,    99,   114,   115,   116,   117,    96,   148,   149,   150,\n     158,   106,   155,   159,    97,   163,   118,   -76,   -76,   -76,\n     -76,   -76,   -76,   -76,   -76,   160,   164,   -76,   -76,    99,\n      13,    14,    15,    16,    17,    18,    19,    20,    91,   106,\n      21,    22,    14,    15,   140,    17,    18,    19,    20,   168,\n     175,    21,    22,   177,   181,   182,   183,    32,   187,   167,\n     188,   169,   170,   171,   185,   189,    53,    51,    32,   176,\n      75,   178,   121,     0,   133,   162,     0,     0,     0,     0,\n     184\n};\n\n#define yypact_value_is_default(yystate) \\\n  ((yystate) == (-90))\n\n#define yytable_value_is_error(yytable_value) \\\n  YYID (0)\n\nstatic const yytype_int16 yycheck[] =\n{\n       1,    67,    68,    10,    93,    94,    76,     3,    76,    14,\n      28,    81,    13,    81,    15,   104,    34,    18,     3,    32,\n      33,    23,    26,    27,    90,    91,    30,    32,    33,    31,\n      78,    35,    80,     0,     1,    31,   102,     4,     5,     6,\n       7,     8,     9,    10,    11,    12,    31,    14,    15,    16,\n      17,    18,    19,    20,    21,    22,    23,    24,    78,    26,\n      80,    26,    69,   133,    31,   133,    31,   156,    26,    27,\n      29,     0,     1,    32,    33,     4,     5,     6,     7,     8,\n       9,    10,    11,    12,   150,    14,    15,    16,    17,    18,\n      19,    20,    21,    22,    23,    24,     0,    26,   164,   100,\n      77,    78,    31,    80,    77,    78,    31,    80,    31,    32,\n      33,     0,     1,    31,   115,     4,     5,     6,     7,     8,\n       9,    10,    11,    26,    27,    14,    15,    16,    17,    18,\n      19,    20,    21,    22,    23,    31,    26,    26,    31,     0,\n       1,    26,    31,     4,     5,     6,     7,     8,     9,    10,\n      11,    26,    31,    14,    15,    16,    17,    18,    19,    20,\n      21,    22,    23,     1,     1,    26,    31,    32,    33,    31,\n      31,     0,     1,    31,    31,     4,     5,     6,     7,     8,\n       9,    10,    11,    31,   185,    14,    15,    16,    17,    18,\n      19,    20,    21,    22,    23,    31,     1,    26,    31,    31,\n       5,     6,    31,     8,     9,    10,    11,    12,    31,    14,\n      15,    16,    17,    18,    19,    20,    31,    31,    31,    25,\n       1,    26,    26,    13,     1,    26,    31,     4,     5,     6,\n       7,     8,     9,    10,    11,    31,    14,    14,    15,    16,\n       4,     5,     6,     7,     8,     9,    10,    11,    33,    26,\n      14,    15,     5,     6,    31,     8,     9,    10,    11,    31,\n      31,    14,    15,    31,    31,    31,    31,    31,    31,   151,\n      31,   153,   154,   155,    34,    31,     7,     6,    31,   161,\n      37,   163,    76,    -1,    79,   116,    -1,    -1,    -1,    -1,\n     172\n};\n\n/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing\n   symbol of state STATE-NUM.  */\nstatic const yytype_uint8 yystos[] =\n{\n       0,     3,    31,    37,    38,    39,    63,    81,    26,    27,\n      79,     0,     1,     4,     5,     6,     7,     8,     9,    10,\n      11,    14,    15,    16,    17,    18,    19,    20,    21,    22,\n      23,    26,    31,    40,    41,    43,    44,    45,    46,    52,\n      53,    55,    59,    61,    64,    65,    67,    69,    70,    71,\n      80,    39,    31,    38,    81,    31,    79,    31,    79,    26,\n      85,    31,    79,    26,    26,    26,    27,    30,    35,    83,\n      84,    31,     1,     1,    47,    47,    56,    58,    62,    76,\n      68,    74,    31,    31,    31,    31,    31,    31,    83,    83,\n      32,    33,    81,    28,    34,    31,    31,     1,    12,    16,\n      18,    19,    20,    21,    22,    24,    26,    31,    42,    48,\n      49,    72,    73,    75,    17,    18,    19,    20,    31,    42,\n      57,    73,    75,    41,    54,    80,    41,    55,    60,    67,\n      80,    23,    31,    74,    77,    41,    55,    66,    67,    80,\n      31,    42,    75,    29,    83,    83,    84,    84,    31,    31,\n      25,    79,    78,    79,    83,    26,    84,    50,     1,    13,\n      31,    79,    78,    26,    14,    82,    83,    82,    31,    82,\n      82,    82,    84,    26,    31,    31,    82,    31,    82,    83,\n      31,    31,    31,    31,    82,    34,    51,    31,    31,    31,\n      79\n};\n\n#define yyerrok\t\t(yyerrstatus = 0)\n#define yyclearin\t(yychar = YYEMPTY)\n#define YYEMPTY\t\t(-2)\n#define YYEOF\t\t0\n\n#define YYACCEPT\tgoto yyacceptlab\n#define YYABORT\t\tgoto yyabortlab\n#define YYERROR\t\tgoto yyerrorlab\n\n\n/* Like YYERROR except do call yyerror.  This remains here temporarily\n   to ease the transition to the new meaning of YYERROR, for GCC.\n   Once GCC version 2 has supplanted version 1, this can go.  However,\n   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated\n   in Bison 2.4.2's NEWS entry, where a plan to phase it out is\n   discussed.  */\n\n#define YYFAIL\t\tgoto yyerrlab\n#if defined YYFAIL\n  /* This is here to suppress warnings from the GCC cpp's\n     -Wunused-macros.  Normally we don't worry about that warning, but\n     some users do, and we want to make it easy for users to remove\n     YYFAIL uses, which will produce warnings from Bison 2.5.  */\n#endif\n\n#define YYRECOVERING()  (!!yyerrstatus)\n\n#define YYBACKUP(Token, Value)\t\t\t\t\t\\\ndo\t\t\t\t\t\t\t\t\\\n  if (yychar == YYEMPTY && yylen == 1)\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      yychar = (Token);\t\t\t\t\t\t\\\n      yylval = (Value);\t\t\t\t\t\t\\\n      YYPOPSTACK (1);\t\t\t\t\t\t\\\n      goto yybackup;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\\\n  else\t\t\t\t\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      yyerror (YY_(\"syntax error: cannot back up\")); \\\n      YYERROR;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\\\nwhile (YYID (0))\n\n\n#define YYTERROR\t1\n#define YYERRCODE\t256\n\n\n/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].\n   If N is 0, then set CURRENT to the empty location which ends\n   the previous symbol: RHS[0] (always defined).  */\n\n#define YYRHSLOC(Rhs, K) ((Rhs)[K])\n#ifndef YYLLOC_DEFAULT\n# define YYLLOC_DEFAULT(Current, Rhs, N)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n      if (YYID (N))                                                    \\\n\t{\t\t\t\t\t\t\t\t\\\n\t  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;\t\\\n\t  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;\t\\\n\t  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;\t\t\\\n\t  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;\t\\\n\t}\t\t\t\t\t\t\t\t\\\n      else\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\\\n\t  (Current).first_line   = (Current).last_line   =\t\t\\\n\t    YYRHSLOC (Rhs, 0).last_line;\t\t\t\t\\\n\t  (Current).first_column = (Current).last_column =\t\t\\\n\t    YYRHSLOC (Rhs, 0).last_column;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    while (YYID (0))\n#endif\n\n\n/* This macro is provided for backward compatibility. */\n\n#ifndef YY_LOCATION_PRINT\n# define YY_LOCATION_PRINT(File, Loc) ((void) 0)\n#endif\n\n\n/* YYLEX -- calling `yylex' with the right arguments.  */\n\n#ifdef YYLEX_PARAM\n# define YYLEX yylex (YYLEX_PARAM)\n#else\n# define YYLEX yylex ()\n#endif\n\n/* Enable debugging if requested.  */\n#if YYDEBUG\n\n# ifndef YYFPRINTF\n#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */\n#  define YYFPRINTF fprintf\n# endif\n\n# define YYDPRINTF(Args)\t\t\t\\\ndo {\t\t\t\t\t\t\\\n  if (yydebug)\t\t\t\t\t\\\n    YYFPRINTF Args;\t\t\t\t\\\n} while (YYID (0))\n\n# define YY_SYMBOL_PRINT(Title, Type, Value, Location)\t\t\t  \\\ndo {\t\t\t\t\t\t\t\t\t  \\\n  if (yydebug)\t\t\t\t\t\t\t\t  \\\n    {\t\t\t\t\t\t\t\t\t  \\\n      YYFPRINTF (stderr, \"%s \", Title);\t\t\t\t\t  \\\n      yy_symbol_print (stderr,\t\t\t\t\t\t  \\\n\t\t  Type, Value); \\\n      YYFPRINTF (stderr, \"\\n\");\t\t\t\t\t\t  \\\n    }\t\t\t\t\t\t\t\t\t  \\\n} while (YYID (0))\n\n\n/*--------------------------------.\n| Print this symbol on YYOUTPUT.  |\n`--------------------------------*/\n\n/*ARGSUSED*/\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)\n#else\nstatic void\nyy_symbol_value_print (yyoutput, yytype, yyvaluep)\n    FILE *yyoutput;\n    int yytype;\n    YYSTYPE const * const yyvaluep;\n#endif\n{\n  if (!yyvaluep)\n    return;\n# ifdef YYPRINT\n  if (yytype < YYNTOKENS)\n    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);\n# else\n  YYUSE (yyoutput);\n# endif\n  switch (yytype)\n    {\n      default:\n\tbreak;\n    }\n}\n\n\n/*--------------------------------.\n| Print this symbol on YYOUTPUT.  |\n`--------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)\n#else\nstatic void\nyy_symbol_print (yyoutput, yytype, yyvaluep)\n    FILE *yyoutput;\n    int yytype;\n    YYSTYPE const * const yyvaluep;\n#endif\n{\n  if (yytype < YYNTOKENS)\n    YYFPRINTF (yyoutput, \"token %s (\", yytname[yytype]);\n  else\n    YYFPRINTF (yyoutput, \"nterm %s (\", yytname[yytype]);\n\n  yy_symbol_value_print (yyoutput, yytype, yyvaluep);\n  YYFPRINTF (yyoutput, \")\");\n}\n\n/*------------------------------------------------------------------.\n| yy_stack_print -- Print the state stack from its BOTTOM up to its |\n| TOP (included).                                                   |\n`------------------------------------------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)\n#else\nstatic void\nyy_stack_print (yybottom, yytop)\n    yytype_int16 *yybottom;\n    yytype_int16 *yytop;\n#endif\n{\n  YYFPRINTF (stderr, \"Stack now\");\n  for (; yybottom <= yytop; yybottom++)\n    {\n      int yybot = *yybottom;\n      YYFPRINTF (stderr, \" %d\", yybot);\n    }\n  YYFPRINTF (stderr, \"\\n\");\n}\n\n# define YY_STACK_PRINT(Bottom, Top)\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\\\n  if (yydebug)\t\t\t\t\t\t\t\\\n    yy_stack_print ((Bottom), (Top));\t\t\t\t\\\n} while (YYID (0))\n\n\n/*------------------------------------------------.\n| Report that the YYRULE is going to be reduced.  |\n`------------------------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_reduce_print (YYSTYPE *yyvsp, int yyrule)\n#else\nstatic void\nyy_reduce_print (yyvsp, yyrule)\n    YYSTYPE *yyvsp;\n    int yyrule;\n#endif\n{\n  int yynrhs = yyr2[yyrule];\n  int yyi;\n  unsigned long int yylno = yyrline[yyrule];\n  YYFPRINTF (stderr, \"Reducing stack by rule %d (line %lu):\\n\",\n\t     yyrule - 1, yylno);\n  /* The symbols being reduced.  */\n  for (yyi = 0; yyi < yynrhs; yyi++)\n    {\n      YYFPRINTF (stderr, \"   $%d = \", yyi + 1);\n      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],\n\t\t       &(yyvsp[(yyi + 1) - (yynrhs)])\n\t\t       \t\t       );\n      YYFPRINTF (stderr, \"\\n\");\n    }\n}\n\n# define YY_REDUCE_PRINT(Rule)\t\t\\\ndo {\t\t\t\t\t\\\n  if (yydebug)\t\t\t\t\\\n    yy_reduce_print (yyvsp, Rule); \\\n} while (YYID (0))\n\n/* Nonzero means print parse trace.  It is left uninitialized so that\n   multiple parsers can coexist.  */\nint yydebug;\n#else /* !YYDEBUG */\n# define YYDPRINTF(Args)\n# define YY_SYMBOL_PRINT(Title, Type, Value, Location)\n# define YY_STACK_PRINT(Bottom, Top)\n# define YY_REDUCE_PRINT(Rule)\n#endif /* !YYDEBUG */\n\n\n/* YYINITDEPTH -- initial size of the parser's stacks.  */\n#ifndef\tYYINITDEPTH\n# define YYINITDEPTH 200\n#endif\n\n/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only\n   if the built-in stack extension method is used).\n\n   Do not make this value too large; the results are undefined if\n   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)\n   evaluated with infinite-precision integer arithmetic.  */\n\n#ifndef YYMAXDEPTH\n# define YYMAXDEPTH 10000\n#endif\n\n\n#if YYERROR_VERBOSE\n\n# ifndef yystrlen\n#  if defined __GLIBC__ && defined _STRING_H\n#   define yystrlen strlen\n#  else\n/* Return the length of YYSTR.  */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic YYSIZE_T\nyystrlen (const char *yystr)\n#else\nstatic YYSIZE_T\nyystrlen (yystr)\n    const char *yystr;\n#endif\n{\n  YYSIZE_T yylen;\n  for (yylen = 0; yystr[yylen]; yylen++)\n    continue;\n  return yylen;\n}\n#  endif\n# endif\n\n# ifndef yystpcpy\n#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE\n#   define yystpcpy stpcpy\n#  else\n/* Copy YYSRC to YYDEST, returning the address of the terminating '\\0' in\n   YYDEST.  */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic char *\nyystpcpy (char *yydest, const char *yysrc)\n#else\nstatic char *\nyystpcpy (yydest, yysrc)\n    char *yydest;\n    const char *yysrc;\n#endif\n{\n  char *yyd = yydest;\n  const char *yys = yysrc;\n\n  while ((*yyd++ = *yys++) != '\\0')\n    continue;\n\n  return yyd - 1;\n}\n#  endif\n# endif\n\n# ifndef yytnamerr\n/* Copy to YYRES the contents of YYSTR after stripping away unnecessary\n   quotes and backslashes, so that it's suitable for yyerror.  The\n   heuristic is that double-quoting is unnecessary unless the string\n   contains an apostrophe, a comma, or backslash (other than\n   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is\n   null, do not copy; instead, return the length of what the result\n   would have been.  */\nstatic YYSIZE_T\nyytnamerr (char *yyres, const char *yystr)\n{\n  if (*yystr == '\"')\n    {\n      YYSIZE_T yyn = 0;\n      char const *yyp = yystr;\n\n      for (;;)\n\tswitch (*++yyp)\n\t  {\n\t  case '\\'':\n\t  case ',':\n\t    goto do_not_strip_quotes;\n\n\t  case '\\\\':\n\t    if (*++yyp != '\\\\')\n\t      goto do_not_strip_quotes;\n\t    /* Fall through.  */\n\t  default:\n\t    if (yyres)\n\t      yyres[yyn] = *yyp;\n\t    yyn++;\n\t    break;\n\n\t  case '\"':\n\t    if (yyres)\n\t      yyres[yyn] = '\\0';\n\t    return yyn;\n\t  }\n    do_not_strip_quotes: ;\n    }\n\n  if (! yyres)\n    return yystrlen (yystr);\n\n  return yystpcpy (yyres, yystr) - yyres;\n}\n# endif\n\n/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message\n   about the unexpected token YYTOKEN for the state stack whose top is\n   YYSSP.\n\n   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is\n   not large enough to hold the message.  In that case, also set\n   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the\n   required number of bytes is too large to store.  */\nstatic int\nyysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,\n                yytype_int16 *yyssp, int yytoken)\n{\n  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);\n  YYSIZE_T yysize = yysize0;\n  YYSIZE_T yysize1;\n  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };\n  /* Internationalized format string. */\n  const char *yyformat = 0;\n  /* Arguments of yyformat. */\n  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];\n  /* Number of reported tokens (one for the \"unexpected\", one per\n     \"expected\"). */\n  int yycount = 0;\n\n  /* There are many possibilities here to consider:\n     - Assume YYFAIL is not used.  It's too flawed to consider.  See\n       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>\n       for details.  YYERROR is fine as it does not invoke this\n       function.\n     - If this state is a consistent state with a default action, then\n       the only way this function was invoked is if the default action\n       is an error action.  In that case, don't check for expected\n       tokens because there are none.\n     - The only way there can be no lookahead present (in yychar) is if\n       this state is a consistent state with a default action.  Thus,\n       detecting the absence of a lookahead is sufficient to determine\n       that there is no unexpected or expected token to report.  In that\n       case, just report a simple \"syntax error\".\n     - Don't assume there isn't a lookahead just because this state is a\n       consistent state with a default action.  There might have been a\n       previous inconsistent state, consistent state with a non-default\n       action, or user semantic action that manipulated yychar.\n     - Of course, the expected token list depends on states to have\n       correct lookahead information, and it depends on the parser not\n       to perform extra reductions after fetching a lookahead from the\n       scanner and before detecting a syntax error.  Thus, state merging\n       (from LALR or IELR) and default reductions corrupt the expected\n       token list.  However, the list is correct for canonical LR with\n       one exception: it will still contain any token that will not be\n       accepted due to an error action in a later state.\n  */\n  if (yytoken != YYEMPTY)\n    {\n      int yyn = yypact[*yyssp];\n      yyarg[yycount++] = yytname[yytoken];\n      if (!yypact_value_is_default (yyn))\n        {\n          /* Start YYX at -YYN if negative to avoid negative indexes in\n             YYCHECK.  In other words, skip the first -YYN actions for\n             this state because they are default actions.  */\n          int yyxbegin = yyn < 0 ? -yyn : 0;\n          /* Stay within bounds of both yycheck and yytname.  */\n          int yychecklim = YYLAST - yyn + 1;\n          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;\n          int yyx;\n\n          for (yyx = yyxbegin; yyx < yyxend; ++yyx)\n            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR\n                && !yytable_value_is_error (yytable[yyx + yyn]))\n              {\n                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)\n                  {\n                    yycount = 1;\n                    yysize = yysize0;\n                    break;\n                  }\n                yyarg[yycount++] = yytname[yyx];\n                yysize1 = yysize + yytnamerr (0, yytname[yyx]);\n                if (! (yysize <= yysize1\n                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))\n                  return 2;\n                yysize = yysize1;\n              }\n        }\n    }\n\n  switch (yycount)\n    {\n# define YYCASE_(N, S)                      \\\n      case N:                               \\\n        yyformat = S;                       \\\n      break\n      YYCASE_(0, YY_(\"syntax error\"));\n      YYCASE_(1, YY_(\"syntax error, unexpected %s\"));\n      YYCASE_(2, YY_(\"syntax error, unexpected %s, expecting %s\"));\n      YYCASE_(3, YY_(\"syntax error, unexpected %s, expecting %s or %s\"));\n      YYCASE_(4, YY_(\"syntax error, unexpected %s, expecting %s or %s or %s\"));\n      YYCASE_(5, YY_(\"syntax error, unexpected %s, expecting %s or %s or %s or %s\"));\n# undef YYCASE_\n    }\n\n  yysize1 = yysize + yystrlen (yyformat);\n  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))\n    return 2;\n  yysize = yysize1;\n\n  if (*yymsg_alloc < yysize)\n    {\n      *yymsg_alloc = 2 * yysize;\n      if (! (yysize <= *yymsg_alloc\n             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))\n        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;\n      return 1;\n    }\n\n  /* Avoid sprintf, as that infringes on the user's name space.\n     Don't have undefined behavior even if the translation\n     produced a string with the wrong number of \"%s\"s.  */\n  {\n    char *yyp = *yymsg;\n    int yyi = 0;\n    while ((*yyp = *yyformat) != '\\0')\n      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)\n        {\n          yyp += yytnamerr (yyp, yyarg[yyi++]);\n          yyformat += 2;\n        }\n      else\n        {\n          yyp++;\n          yyformat++;\n        }\n  }\n  return 0;\n}\n#endif /* YYERROR_VERBOSE */\n\n/*-----------------------------------------------.\n| Release the memory associated to this symbol.  |\n`-----------------------------------------------*/\n\n/*ARGSUSED*/\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)\n#else\nstatic void\nyydestruct (yymsg, yytype, yyvaluep)\n    const char *yymsg;\n    int yytype;\n    YYSTYPE *yyvaluep;\n#endif\n{\n  YYUSE (yyvaluep);\n\n  if (!yymsg)\n    yymsg = \"Deleting\";\n  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);\n\n  switch (yytype)\n    {\n      case 53: /* \"choice_entry\" */\n\n\t{\n\tfprintf(stderr, \"%s:%d: missing end statement for this entry\\n\",\n\t\t(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);\n\tif (current_menu == (yyvaluep->menu))\n\t\tmenu_end_menu();\n};\n\n\tbreak;\n      case 59: /* \"if_entry\" */\n\n\t{\n\tfprintf(stderr, \"%s:%d: missing end statement for this entry\\n\",\n\t\t(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);\n\tif (current_menu == (yyvaluep->menu))\n\t\tmenu_end_menu();\n};\n\n\tbreak;\n      case 65: /* \"menu_entry\" */\n\n\t{\n\tfprintf(stderr, \"%s:%d: missing end statement for this entry\\n\",\n\t\t(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);\n\tif (current_menu == (yyvaluep->menu))\n\t\tmenu_end_menu();\n};\n\n\tbreak;\n\n      default:\n\tbreak;\n    }\n}\n\n\n/* Prevent warnings from -Wmissing-prototypes.  */\n#ifdef YYPARSE_PARAM\n#if defined __STDC__ || defined __cplusplus\nint yyparse (void *YYPARSE_PARAM);\n#else\nint yyparse ();\n#endif\n#else /* ! YYPARSE_PARAM */\n#if defined __STDC__ || defined __cplusplus\nint yyparse (void);\n#else\nint yyparse ();\n#endif\n#endif /* ! YYPARSE_PARAM */\n\n\n/* The lookahead symbol.  */\nint yychar;\n\n/* The semantic value of the lookahead symbol.  */\nYYSTYPE yylval;\n\n/* Number of syntax errors so far.  */\nint yynerrs;\n\n\n/*----------.\n| yyparse.  |\n`----------*/\n\n#ifdef YYPARSE_PARAM\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nint\nyyparse (void *YYPARSE_PARAM)\n#else\nint\nyyparse (YYPARSE_PARAM)\n    void *YYPARSE_PARAM;\n#endif\n#else /* ! YYPARSE_PARAM */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nint\nyyparse (void)\n#else\nint\nyyparse ()\n\n#endif\n#endif\n{\n    int yystate;\n    /* Number of tokens to shift before error messages enabled.  */\n    int yyerrstatus;\n\n    /* The stacks and their tools:\n       `yyss': related to states.\n       `yyvs': related to semantic values.\n\n       Refer to the stacks thru separate pointers, to allow yyoverflow\n       to reallocate them elsewhere.  */\n\n    /* The state stack.  */\n    yytype_int16 yyssa[YYINITDEPTH];\n    yytype_int16 *yyss;\n    yytype_int16 *yyssp;\n\n    /* The semantic value stack.  */\n    YYSTYPE yyvsa[YYINITDEPTH];\n    YYSTYPE *yyvs;\n    YYSTYPE *yyvsp;\n\n    YYSIZE_T yystacksize;\n\n  int yyn;\n  int yyresult;\n  /* Lookahead token as an internal (translated) token number.  */\n  int yytoken;\n  /* The variables used to return semantic value and location from the\n     action routines.  */\n  YYSTYPE yyval;\n\n#if YYERROR_VERBOSE\n  /* Buffer for error messages, and its allocated size.  */\n  char yymsgbuf[128];\n  char *yymsg = yymsgbuf;\n  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;\n#endif\n\n#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))\n\n  /* The number of symbols on the RHS of the reduced rule.\n     Keep to zero when no symbol should be popped.  */\n  int yylen = 0;\n\n  yytoken = 0;\n  yyss = yyssa;\n  yyvs = yyvsa;\n  yystacksize = YYINITDEPTH;\n\n  YYDPRINTF ((stderr, \"Starting parse\\n\"));\n\n  yystate = 0;\n  yyerrstatus = 0;\n  yynerrs = 0;\n  yychar = YYEMPTY; /* Cause a token to be read.  */\n\n  /* Initialize stack pointers.\n     Waste one element of value and location stack\n     so that they stay on the same level as the state stack.\n     The wasted elements are never initialized.  */\n  yyssp = yyss;\n  yyvsp = yyvs;\n\n  goto yysetstate;\n\n/*------------------------------------------------------------.\n| yynewstate -- Push a new state, which is found in yystate.  |\n`------------------------------------------------------------*/\n yynewstate:\n  /* In all cases, when you get here, the value and location stacks\n     have just been pushed.  So pushing a state here evens the stacks.  */\n  yyssp++;\n\n yysetstate:\n  *yyssp = yystate;\n\n  if (yyss + yystacksize - 1 <= yyssp)\n    {\n      /* Get the current used size of the three stacks, in elements.  */\n      YYSIZE_T yysize = yyssp - yyss + 1;\n\n#ifdef yyoverflow\n      {\n\t/* Give user a chance to reallocate the stack.  Use copies of\n\t   these so that the &'s don't force the real ones into\n\t   memory.  */\n\tYYSTYPE *yyvs1 = yyvs;\n\tyytype_int16 *yyss1 = yyss;\n\n\t/* Each stack pointer address is followed by the size of the\n\t   data in use in that stack, in bytes.  This used to be a\n\t   conditional around just the two extra args, but that might\n\t   be undefined if yyoverflow is a macro.  */\n\tyyoverflow (YY_(\"memory exhausted\"),\n\t\t    &yyss1, yysize * sizeof (*yyssp),\n\t\t    &yyvs1, yysize * sizeof (*yyvsp),\n\t\t    &yystacksize);\n\n\tyyss = yyss1;\n\tyyvs = yyvs1;\n      }\n#else /* no yyoverflow */\n# ifndef YYSTACK_RELOCATE\n      goto yyexhaustedlab;\n# else\n      /* Extend the stack our own way.  */\n      if (YYMAXDEPTH <= yystacksize)\n\tgoto yyexhaustedlab;\n      yystacksize *= 2;\n      if (YYMAXDEPTH < yystacksize)\n\tyystacksize = YYMAXDEPTH;\n\n      {\n\tyytype_int16 *yyss1 = yyss;\n\tunion yyalloc *yyptr =\n\t  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));\n\tif (! yyptr)\n\t  goto yyexhaustedlab;\n\tYYSTACK_RELOCATE (yyss_alloc, yyss);\n\tYYSTACK_RELOCATE (yyvs_alloc, yyvs);\n#  undef YYSTACK_RELOCATE\n\tif (yyss1 != yyssa)\n\t  YYSTACK_FREE (yyss1);\n      }\n# endif\n#endif /* no yyoverflow */\n\n      yyssp = yyss + yysize - 1;\n      yyvsp = yyvs + yysize - 1;\n\n      YYDPRINTF ((stderr, \"Stack size increased to %lu\\n\",\n\t\t  (unsigned long int) yystacksize));\n\n      if (yyss + yystacksize - 1 <= yyssp)\n\tYYABORT;\n    }\n\n  YYDPRINTF ((stderr, \"Entering state %d\\n\", yystate));\n\n  if (yystate == YYFINAL)\n    YYACCEPT;\n\n  goto yybackup;\n\n/*-----------.\n| yybackup.  |\n`-----------*/\nyybackup:\n\n  /* Do appropriate processing given the current state.  Read a\n     lookahead token if we need one and don't already have one.  */\n\n  /* First try to decide what to do without reference to lookahead token.  */\n  yyn = yypact[yystate];\n  if (yypact_value_is_default (yyn))\n    goto yydefault;\n\n  /* Not known => get a lookahead token if don't already have one.  */\n\n  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */\n  if (yychar == YYEMPTY)\n    {\n      YYDPRINTF ((stderr, \"Reading a token: \"));\n      yychar = YYLEX;\n    }\n\n  if (yychar <= YYEOF)\n    {\n      yychar = yytoken = YYEOF;\n      YYDPRINTF ((stderr, \"Now at end of input.\\n\"));\n    }\n  else\n    {\n      yytoken = YYTRANSLATE (yychar);\n      YY_SYMBOL_PRINT (\"Next token is\", yytoken, &yylval, &yylloc);\n    }\n\n  /* If the proper action on seeing token YYTOKEN is to reduce or to\n     detect an error, take that action.  */\n  yyn += yytoken;\n  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)\n    goto yydefault;\n  yyn = yytable[yyn];\n  if (yyn <= 0)\n    {\n      if (yytable_value_is_error (yyn))\n        goto yyerrlab;\n      yyn = -yyn;\n      goto yyreduce;\n    }\n\n  /* Count tokens shifted since error; after three, turn off error\n     status.  */\n  if (yyerrstatus)\n    yyerrstatus--;\n\n  /* Shift the lookahead token.  */\n  YY_SYMBOL_PRINT (\"Shifting\", yytoken, &yylval, &yylloc);\n\n  /* Discard the shifted token.  */\n  yychar = YYEMPTY;\n\n  yystate = yyn;\n  *++yyvsp = yylval;\n\n  goto yynewstate;\n\n\n/*-----------------------------------------------------------.\n| yydefault -- do the default action for the current state.  |\n`-----------------------------------------------------------*/\nyydefault:\n  yyn = yydefact[yystate];\n  if (yyn == 0)\n    goto yyerrlab;\n  goto yyreduce;\n\n\n/*-----------------------------.\n| yyreduce -- Do a reduction.  |\n`-----------------------------*/\nyyreduce:\n  /* yyn is the number of a rule to reduce with.  */\n  yylen = yyr2[yyn];\n\n  /* If YYLEN is nonzero, implement the default value of the action:\n     `$$ = $1'.\n\n     Otherwise, the following line sets YYVAL to garbage.\n     This behavior is undocumented and Bison\n     users should not rely upon it.  Assigning to YYVAL\n     unconditionally makes the parser a bit smaller, and it avoids a\n     GCC warning that YYVAL may be used uninitialized.  */\n  yyval = yyvsp[1-yylen];\n\n\n  YY_REDUCE_PRINT (yyn);\n  switch (yyn)\n    {\n        case 10:\n\n    { zconf_error(\"unexpected end statement\"); }\n    break;\n\n  case 11:\n\n    { zconf_error(\"unknown statement \\\"%s\\\"\", (yyvsp[(2) - (4)].string)); }\n    break;\n\n  case 12:\n\n    {\n\tzconf_error(\"unexpected option \\\"%s\\\"\", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);\n}\n    break;\n\n  case 13:\n\n    { zconf_error(\"invalid statement\"); }\n    break;\n\n  case 28:\n\n    { zconf_error(\"unknown option \\\"%s\\\"\", (yyvsp[(1) - (3)].string)); }\n    break;\n\n  case 29:\n\n    { zconf_error(\"invalid option\"); }\n    break;\n\n  case 30:\n\n    {\n\tstruct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);\n\tsym->flags |= SYMBOL_OPTIONAL;\n\tmenu_add_entry(sym);\n\tprintd(DEBUG_PARSE, \"%s:%d:config %s\\n\", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));\n}\n    break;\n\n  case 31:\n\n    {\n\tmenu_end_entry();\n\tprintd(DEBUG_PARSE, \"%s:%d:endconfig\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 32:\n\n    {\n\tstruct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);\n\tsym->flags |= SYMBOL_OPTIONAL;\n\tmenu_add_entry(sym);\n\tprintd(DEBUG_PARSE, \"%s:%d:menuconfig %s\\n\", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));\n}\n    break;\n\n  case 33:\n\n    {\n\tif (current_entry->prompt)\n\t\tcurrent_entry->prompt->type = P_MENU;\n\telse\n\t\tzconfprint(\"warning: menuconfig statement without prompt\");\n\tmenu_end_entry();\n\tprintd(DEBUG_PARSE, \"%s:%d:endconfig\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 41:\n\n    {\n\tmenu_set_type((yyvsp[(1) - (3)].id)->stype);\n\tprintd(DEBUG_PARSE, \"%s:%d:type(%u)\\n\",\n\t\tzconf_curname(), zconf_lineno(),\n\t\t(yyvsp[(1) - (3)].id)->stype);\n}\n    break;\n\n  case 42:\n\n    {\n\tmenu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));\n\tprintd(DEBUG_PARSE, \"%s:%d:prompt\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 43:\n\n    {\n\tmenu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));\n\tif ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN)\n\t\tmenu_set_type((yyvsp[(1) - (4)].id)->stype);\n\tprintd(DEBUG_PARSE, \"%s:%d:default(%u)\\n\",\n\t\tzconf_curname(), zconf_lineno(),\n\t\t(yyvsp[(1) - (4)].id)->stype);\n}\n    break;\n\n  case 44:\n\n    {\n\tmenu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));\n\tprintd(DEBUG_PARSE, \"%s:%d:select\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 45:\n\n    {\n\tmenu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));\n\tprintd(DEBUG_PARSE, \"%s:%d:range\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 48:\n\n    {\n\tconst struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));\n\tif (id && id->flags & TF_OPTION)\n\t\tmenu_add_option(id->token, (yyvsp[(3) - (3)].string));\n\telse\n\t\tzconfprint(\"warning: ignoring unknown option %s\", (yyvsp[(2) - (3)].string));\n\tfree((yyvsp[(2) - (3)].string));\n}\n    break;\n\n  case 49:\n\n    { (yyval.string) = NULL; }\n    break;\n\n  case 50:\n\n    { (yyval.string) = (yyvsp[(2) - (2)].string); }\n    break;\n\n  case 51:\n\n    {\n\tstruct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);\n\tsym->flags |= SYMBOL_AUTO;\n\tmenu_add_entry(sym);\n\tmenu_add_expr(P_CHOICE, NULL, NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:choice\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 52:\n\n    {\n\t(yyval.menu) = menu_add_menu();\n}\n    break;\n\n  case 53:\n\n    {\n\tif (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endchoice\\n\", zconf_curname(), zconf_lineno());\n\t}\n}\n    break;\n\n  case 61:\n\n    {\n\tmenu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));\n\tprintd(DEBUG_PARSE, \"%s:%d:prompt\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 62:\n\n    {\n\tif ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {\n\t\tmenu_set_type((yyvsp[(1) - (3)].id)->stype);\n\t\tprintd(DEBUG_PARSE, \"%s:%d:type(%u)\\n\",\n\t\t\tzconf_curname(), zconf_lineno(),\n\t\t\t(yyvsp[(1) - (3)].id)->stype);\n\t} else\n\t\tYYERROR;\n}\n    break;\n\n  case 63:\n\n    {\n\tcurrent_entry->sym->flags |= SYMBOL_OPTIONAL;\n\tprintd(DEBUG_PARSE, \"%s:%d:optional\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 64:\n\n    {\n\tif ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {\n\t\tmenu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));\n\t\tprintd(DEBUG_PARSE, \"%s:%d:default\\n\",\n\t\t\tzconf_curname(), zconf_lineno());\n\t} else\n\t\tYYERROR;\n}\n    break;\n\n  case 67:\n\n    {\n\tprintd(DEBUG_PARSE, \"%s:%d:if\\n\", zconf_curname(), zconf_lineno());\n\tmenu_add_entry(NULL);\n\tmenu_add_dep((yyvsp[(2) - (3)].expr));\n\t(yyval.menu) = menu_add_menu();\n}\n    break;\n\n  case 68:\n\n    {\n\tif (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endif\\n\", zconf_curname(), zconf_lineno());\n\t}\n}\n    break;\n\n  case 74:\n\n    {\n\tmenu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);\n}\n    break;\n\n  case 75:\n\n    {\n\tmenu_add_entry(NULL);\n\tmenu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:menu\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 76:\n\n    {\n\t(yyval.menu) = menu_add_menu();\n}\n    break;\n\n  case 77:\n\n    {\n\tif (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endmenu\\n\", zconf_curname(), zconf_lineno());\n\t}\n}\n    break;\n\n  case 83:\n\n    {\n\tprintd(DEBUG_PARSE, \"%s:%d:source %s\\n\", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));\n\tzconf_nextfile((yyvsp[(2) - (3)].string));\n}\n    break;\n\n  case 84:\n\n    {\n\tmenu_add_entry(NULL);\n\tmenu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:comment\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 85:\n\n    {\n\tmenu_end_entry();\n}\n    break;\n\n  case 86:\n\n    {\n\tprintd(DEBUG_PARSE, \"%s:%d:help\\n\", zconf_curname(), zconf_lineno());\n\tzconf_starthelp();\n}\n    break;\n\n  case 87:\n\n    {\n\tcurrent_entry->help = (yyvsp[(2) - (2)].string);\n}\n    break;\n\n  case 92:\n\n    {\n\tmenu_add_dep((yyvsp[(3) - (4)].expr));\n\tprintd(DEBUG_PARSE, \"%s:%d:depends on\\n\", zconf_curname(), zconf_lineno());\n}\n    break;\n\n  case 96:\n\n    {\n\tmenu_add_visibility((yyvsp[(2) - (2)].expr));\n}\n    break;\n\n  case 98:\n\n    {\n\tmenu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));\n}\n    break;\n\n  case 101:\n\n    { (yyval.id) = (yyvsp[(1) - (2)].id); }\n    break;\n\n  case 102:\n\n    { (yyval.id) = (yyvsp[(1) - (2)].id); }\n    break;\n\n  case 103:\n\n    { (yyval.id) = (yyvsp[(1) - (2)].id); }\n    break;\n\n  case 106:\n\n    { (yyval.expr) = NULL; }\n    break;\n\n  case 107:\n\n    { (yyval.expr) = (yyvsp[(2) - (2)].expr); }\n    break;\n\n  case 108:\n\n    { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); }\n    break;\n\n  case 109:\n\n    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }\n    break;\n\n  case 110:\n\n    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }\n    break;\n\n  case 111:\n\n    { (yyval.expr) = (yyvsp[(2) - (3)].expr); }\n    break;\n\n  case 112:\n\n    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); }\n    break;\n\n  case 113:\n\n    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }\n    break;\n\n  case 114:\n\n    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }\n    break;\n\n  case 115:\n\n    { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); }\n    break;\n\n  case 116:\n\n    { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); }\n    break;\n\n  case 117:\n\n    { (yyval.string) = NULL; }\n    break;\n\n\n\n      default: break;\n    }\n  /* User semantic actions sometimes alter yychar, and that requires\n     that yytoken be updated with the new translation.  We take the\n     approach of translating immediately before every use of yytoken.\n     One alternative is translating here after every semantic action,\n     but that translation would be missed if the semantic action invokes\n     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or\n     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an\n     incorrect destructor might then be invoked immediately.  In the\n     case of YYERROR or YYBACKUP, subsequent parser actions might lead\n     to an incorrect destructor call or verbose syntax error message\n     before the lookahead is translated.  */\n  YY_SYMBOL_PRINT (\"-> $$ =\", yyr1[yyn], &yyval, &yyloc);\n\n  YYPOPSTACK (yylen);\n  yylen = 0;\n  YY_STACK_PRINT (yyss, yyssp);\n\n  *++yyvsp = yyval;\n\n  /* Now `shift' the result of the reduction.  Determine what state\n     that goes to, based on the state we popped back to and the rule\n     number reduced by.  */\n\n  yyn = yyr1[yyn];\n\n  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;\n  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)\n    yystate = yytable[yystate];\n  else\n    yystate = yydefgoto[yyn - YYNTOKENS];\n\n  goto yynewstate;\n\n\n/*------------------------------------.\n| yyerrlab -- here on detecting error |\n`------------------------------------*/\nyyerrlab:\n  /* Make sure we have latest lookahead translation.  See comments at\n     user semantic actions for why this is necessary.  */\n  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);\n\n  /* If not already recovering from an error, report this error.  */\n  if (!yyerrstatus)\n    {\n      ++yynerrs;\n#if ! YYERROR_VERBOSE\n      yyerror (YY_(\"syntax error\"));\n#else\n# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \\\n                                        yyssp, yytoken)\n      {\n        char const *yymsgp = YY_(\"syntax error\");\n        int yysyntax_error_status;\n        yysyntax_error_status = YYSYNTAX_ERROR;\n        if (yysyntax_error_status == 0)\n          yymsgp = yymsg;\n        else if (yysyntax_error_status == 1)\n          {\n            if (yymsg != yymsgbuf)\n              YYSTACK_FREE (yymsg);\n            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);\n            if (!yymsg)\n              {\n                yymsg = yymsgbuf;\n                yymsg_alloc = sizeof yymsgbuf;\n                yysyntax_error_status = 2;\n              }\n            else\n              {\n                yysyntax_error_status = YYSYNTAX_ERROR;\n                yymsgp = yymsg;\n              }\n          }\n        yyerror (yymsgp);\n        if (yysyntax_error_status == 2)\n          goto yyexhaustedlab;\n      }\n# undef YYSYNTAX_ERROR\n#endif\n    }\n\n\n\n  if (yyerrstatus == 3)\n    {\n      /* If just tried and failed to reuse lookahead token after an\n\t error, discard it.  */\n\n      if (yychar <= YYEOF)\n\t{\n\t  /* Return failure if at end of input.  */\n\t  if (yychar == YYEOF)\n\t    YYABORT;\n\t}\n      else\n\t{\n\t  yydestruct (\"Error: discarding\",\n\t\t      yytoken, &yylval);\n\t  yychar = YYEMPTY;\n\t}\n    }\n\n  /* Else will try to reuse lookahead token after shifting the error\n     token.  */\n  goto yyerrlab1;\n\n\n/*---------------------------------------------------.\n| yyerrorlab -- error raised explicitly by YYERROR.  |\n`---------------------------------------------------*/\nyyerrorlab:\n\n  /* Pacify compilers like GCC when the user code never invokes\n     YYERROR and the label yyerrorlab therefore never appears in user\n     code.  */\n  if (/*CONSTCOND*/ 0)\n     goto yyerrorlab;\n\n  /* Do not reclaim the symbols of the rule which action triggered\n     this YYERROR.  */\n  YYPOPSTACK (yylen);\n  yylen = 0;\n  YY_STACK_PRINT (yyss, yyssp);\n  yystate = *yyssp;\n  goto yyerrlab1;\n\n\n/*-------------------------------------------------------------.\n| yyerrlab1 -- common code for both syntax error and YYERROR.  |\n`-------------------------------------------------------------*/\nyyerrlab1:\n  yyerrstatus = 3;\t/* Each real token shifted decrements this.  */\n\n  for (;;)\n    {\n      yyn = yypact[yystate];\n      if (!yypact_value_is_default (yyn))\n\t{\n\t  yyn += YYTERROR;\n\t  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)\n\t    {\n\t      yyn = yytable[yyn];\n\t      if (0 < yyn)\n\t\tbreak;\n\t    }\n\t}\n\n      /* Pop the current state because it cannot handle the error token.  */\n      if (yyssp == yyss)\n\tYYABORT;\n\n\n      yydestruct (\"Error: popping\",\n\t\t  yystos[yystate], yyvsp);\n      YYPOPSTACK (1);\n      yystate = *yyssp;\n      YY_STACK_PRINT (yyss, yyssp);\n    }\n\n  *++yyvsp = yylval;\n\n\n  /* Shift the error token.  */\n  YY_SYMBOL_PRINT (\"Shifting\", yystos[yyn], yyvsp, yylsp);\n\n  yystate = yyn;\n  goto yynewstate;\n\n\n/*-------------------------------------.\n| yyacceptlab -- YYACCEPT comes here.  |\n`-------------------------------------*/\nyyacceptlab:\n  yyresult = 0;\n  goto yyreturn;\n\n/*-----------------------------------.\n| yyabortlab -- YYABORT comes here.  |\n`-----------------------------------*/\nyyabortlab:\n  yyresult = 1;\n  goto yyreturn;\n\n#if !defined(yyoverflow) || YYERROR_VERBOSE\n/*-------------------------------------------------.\n| yyexhaustedlab -- memory exhaustion comes here.  |\n`-------------------------------------------------*/\nyyexhaustedlab:\n  yyerror (YY_(\"memory exhausted\"));\n  yyresult = 2;\n  /* Fall through.  */\n#endif\n\nyyreturn:\n  if (yychar != YYEMPTY)\n    {\n      /* Make sure we have latest lookahead translation.  See comments at\n         user semantic actions for why this is necessary.  */\n      yytoken = YYTRANSLATE (yychar);\n      yydestruct (\"Cleanup: discarding lookahead\",\n                  yytoken, &yylval);\n    }\n  /* Do not reclaim the symbols of the rule which action triggered\n     this YYABORT or YYACCEPT.  */\n  YYPOPSTACK (yylen);\n  YY_STACK_PRINT (yyss, yyssp);\n  while (yyssp != yyss)\n    {\n      yydestruct (\"Cleanup: popping\",\n\t\t  yystos[*yyssp], yyvsp);\n      YYPOPSTACK (1);\n    }\n#ifndef yyoverflow\n  if (yyss != yyssa)\n    YYSTACK_FREE (yyss);\n#endif\n#if YYERROR_VERBOSE\n  if (yymsg != yymsgbuf)\n    YYSTACK_FREE (yymsg);\n#endif\n  /* Make sure YYID is used.  */\n  return YYID (yyresult);\n}\n\n\n\n\n\nvoid conf_parse(const char *name)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tzconf_initscan(name);\n\n\tsym_init();\n\t_menu_init();\n\trootmenu.prompt = menu_add_prompt(P_MENU, \"FROSTED kernel configuration\", NULL);\n\n\tif (getenv(\"ZCONF_DEBUG\"))\n\t\tzconfdebug = 1;\n\tzconfparse();\n\tif (zconfnerrs)\n\t\texit(1);\n\tif (!modules_sym)\n\t\tmodules_sym = sym_find( \"n\" );\n\n\trootmenu.prompt->text = _(rootmenu.prompt->text);\n\trootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);\n\n\tmenu_finalize(&rootmenu);\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_check_deps(sym))\n\t\t\tzconfnerrs++;\n        }\n\tif (zconfnerrs)\n\t\texit(1);\n\tsym_set_change_count(1);\n}\n\nstatic const char *zconf_tokenname(int token)\n{\n\tswitch (token) {\n\tcase T_MENU:\t\treturn \"menu\";\n\tcase T_ENDMENU:\t\treturn \"endmenu\";\n\tcase T_CHOICE:\t\treturn \"choice\";\n\tcase T_ENDCHOICE:\treturn \"endchoice\";\n\tcase T_IF:\t\treturn \"if\";\n\tcase T_ENDIF:\t\treturn \"endif\";\n\tcase T_DEPENDS:\t\treturn \"depends\";\n\tcase T_VISIBLE:\t\treturn \"visible\";\n\t}\n\treturn \"<token>\";\n}\n\nstatic bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)\n{\n\tif (id->token != endtoken) {\n\t\tzconf_error(\"unexpected '%s' within %s block\",\n\t\t\tkconf_id_strings + id->name, zconf_tokenname(starttoken));\n\t\tzconfnerrs++;\n\t\treturn false;\n\t}\n\tif (current_menu->file != current_file) {\n\t\tzconf_error(\"'%s' in different file than '%s'\",\n\t\t\tkconf_id_strings + id->name, zconf_tokenname(starttoken));\n\t\tfprintf(stderr, \"%s:%d: location of the '%s'\\n\",\n\t\t\tcurrent_menu->file->name, current_menu->lineno,\n\t\t\tzconf_tokenname(starttoken));\n\t\tzconfnerrs++;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nstatic void zconfprint(const char *err, ...)\n{\n\tva_list ap;\n\n\tfprintf(stderr, \"%s:%d: \", zconf_curname(), zconf_lineno());\n\tva_start(ap, err);\n\tvfprintf(stderr, err, ap);\n\tva_end(ap);\n\tfprintf(stderr, \"\\n\");\n}\n\nstatic void zconf_error(const char *err, ...)\n{\n\tva_list ap;\n\n\tzconfnerrs++;\n\tfprintf(stderr, \"%s:%d: \", zconf_curname(), zconf_lineno());\n\tva_start(ap, err);\n\tvfprintf(stderr, err, ap);\n\tva_end(ap);\n\tfprintf(stderr, \"\\n\");\n}\n\nstatic void zconferror(const char *err)\n{\n\tfprintf(stderr, \"%s:%d: %s\\n\", zconf_curname(), zconf_lineno() + 1, err);\n}\n\nstatic void print_quoted_string(FILE *out, const char *str)\n{\n\tconst char *p;\n\tint len;\n\n\tputc('\"', out);\n\twhile ((p = strchr(str, '\"'))) {\n\t\tlen = p - str;\n\t\tif (len)\n\t\t\tfprintf(out, \"%.*s\", len, str);\n\t\tfputs(\"\\\\\\\"\", out);\n\t\tstr = p + 1;\n\t}\n\tfputs(str, out);\n\tputc('\"', out);\n}\n\nstatic void print_symbol(FILE *out, struct menu *menu)\n{\n\tstruct symbol *sym = menu->sym;\n\tstruct property *prop;\n\n\tif (sym_is_choice(sym))\n\t\tfprintf(out, \"\\nchoice\\n\");\n\telse\n\t\tfprintf(out, \"\\nconfig %s\\n\", sym->name);\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\t\tfputs(\"  boolean\\n\", out);\n\t\tbreak;\n\tcase S_TRISTATE:\n\t\tfputs(\"  tristate\\n\", out);\n\t\tbreak;\n\tcase S_STRING:\n\t\tfputs(\"  string\\n\", out);\n\t\tbreak;\n\tcase S_INT:\n\t\tfputs(\"  integer\\n\", out);\n\t\tbreak;\n\tcase S_HEX:\n\t\tfputs(\"  hex\\n\", out);\n\t\tbreak;\n\tdefault:\n\t\tfputs(\"  ???\\n\", out);\n\t\tbreak;\n\t}\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tif (prop->menu != menu)\n\t\t\tcontinue;\n\t\tswitch (prop->type) {\n\t\tcase P_PROMPT:\n\t\t\tfputs(\"  prompt \", out);\n\t\t\tprint_quoted_string(out, prop->text);\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\" if \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t}\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_DEFAULT:\n\t\t\tfputs( \"  default \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\" if \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t}\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_CHOICE:\n\t\t\tfputs(\"  #choice value\\n\", out);\n\t\t\tbreak;\n\t\tcase P_SELECT:\n\t\t\tfputs( \"  select \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_RANGE:\n\t\t\tfputs( \"  range \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_MENU:\n\t\t\tfputs( \"  menu \", out);\n\t\t\tprint_quoted_string(out, prop->text);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfprintf(out, \"  unknown prop %d!\\n\", prop->type);\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (menu->help) {\n\t\tint len = strlen(menu->help);\n\t\twhile (menu->help[--len] == '\\n')\n\t\t\tmenu->help[len] = 0;\n\t\tfprintf(out, \"  help\\n%s\\n\", menu->help);\n\t}\n}\n\nvoid zconfdump(FILE *out)\n{\n\tstruct property *prop;\n\tstruct symbol *sym;\n\tstruct menu *menu;\n\n\tmenu = rootmenu.list;\n\twhile (menu) {\n\t\tif ((sym = menu->sym))\n\t\t\tprint_symbol(out, menu);\n\t\telse if ((prop = menu->prompt)) {\n\t\t\tswitch (prop->type) {\n\t\t\tcase P_COMMENT:\n\t\t\t\tfputs(\"\\ncomment \", out);\n\t\t\t\tprint_quoted_string(out, prop->text);\n\t\t\t\tfputs(\"\\n\", out);\n\t\t\t\tbreak;\n\t\t\tcase P_MENU:\n\t\t\t\tfputs(\"\\nmenu \", out);\n\t\t\t\tprint_quoted_string(out, prop->text);\n\t\t\t\tfputs(\"\\n\", out);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t;\n\t\t\t}\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\"  depends \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t\tfputc('\\n', out);\n\t\t\t}\n\t\t}\n\n\t\tif (menu->list)\n\t\t\tmenu = menu->list;\n\t\telse if (menu->next)\n\t\t\tmenu = menu->next;\n\t\telse while ((menu = menu->parent)) {\n\t\t\tif (menu->prompt && menu->prompt->type == P_MENU)\n\t\t\t\tfputs(\"\\nendmenu\\n\", out);\n\t\t\tif (menu->next) {\n\t\t\t\tmenu = menu->next;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#include \"zconf.lex.c\"\n#include \"util.c\"\n#include \"confdata.c\"\n#include \"expr.c\"\n#include \"symbol.c\"\n#include \"menu.c\"\n\n"
  },
  {
    "path": "kconfig/zconf.y",
    "content": "%{\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n * Released under the terms of the GNU GPL v2.0.\n */\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdbool.h>\n\n#include \"lkc.h\"\n\n#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)\n\n#define PRINTD\t\t0x0001\n#define DEBUG_PARSE\t0x0002\n\nint cdebug = PRINTD;\n\nextern int zconflex(void);\nstatic void zconfprint(const char *err, ...);\nstatic void zconf_error(const char *err, ...);\nstatic void zconferror(const char *err);\nstatic bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);\n\nstruct symbol *symbol_hash[SYMBOL_HASHSIZE];\n\nstatic struct menu *current_menu, *current_entry;\n\n%}\n%expect 30\n\n%union\n{\n\tchar *string;\n\tstruct file *file;\n\tstruct symbol *symbol;\n\tstruct expr *expr;\n\tstruct menu *menu;\n\tconst struct kconf_id *id;\n}\n\n%token <id>T_MAINMENU\n%token <id>T_MENU\n%token <id>T_ENDMENU\n%token <id>T_SOURCE\n%token <id>T_CHOICE\n%token <id>T_ENDCHOICE\n%token <id>T_COMMENT\n%token <id>T_CONFIG\n%token <id>T_MENUCONFIG\n%token <id>T_HELP\n%token <string> T_HELPTEXT\n%token <id>T_IF\n%token <id>T_ENDIF\n%token <id>T_DEPENDS\n%token <id>T_OPTIONAL\n%token <id>T_PROMPT\n%token <id>T_TYPE\n%token <id>T_DEFAULT\n%token <id>T_SELECT\n%token <id>T_RANGE\n%token <id>T_VISIBLE\n%token <id>T_OPTION\n%token <id>T_ON\n%token <string> T_WORD\n%token <string> T_WORD_QUOTE\n%token T_UNEQUAL\n%token T_CLOSE_PAREN\n%token T_OPEN_PAREN\n%token T_EOL\n\n%left T_OR\n%left T_AND\n%left T_EQUAL T_UNEQUAL\n%nonassoc T_NOT\n\n%type <string> prompt\n%type <symbol> symbol\n%type <expr> expr\n%type <expr> if_expr\n%type <id> end\n%type <id> option_name\n%type <menu> if_entry menu_entry choice_entry\n%type <string> symbol_option_arg word_opt\n\n%destructor {\n\tfprintf(stderr, \"%s:%d: missing end statement for this entry\\n\",\n\t\t$$->file->name, $$->lineno);\n\tif (current_menu == $$)\n\t\tmenu_end_menu();\n} if_entry menu_entry choice_entry\n\n%{\n/* Include zconf.hash.c here so it can see the token constants. */\n#include \"zconf.hash.c\"\n%}\n\n%%\ninput: nl start | start;\n\nstart: mainmenu_stmt stmt_list | stmt_list;\n\nstmt_list:\n\t  /* empty */\n\t| stmt_list common_stmt\n\t| stmt_list choice_stmt\n\t| stmt_list menu_stmt\n\t| stmt_list end\t\t\t{ zconf_error(\"unexpected end statement\"); }\n\t| stmt_list T_WORD error T_EOL\t{ zconf_error(\"unknown statement \\\"%s\\\"\", $2); }\n\t| stmt_list option_name error T_EOL\n{\n\tzconf_error(\"unexpected option \\\"%s\\\"\", kconf_id_strings + $2->name);\n}\n\t| stmt_list error T_EOL\t\t{ zconf_error(\"invalid statement\"); }\n;\n\noption_name:\n\tT_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE\n;\n\ncommon_stmt:\n\t  T_EOL\n\t| if_stmt\n\t| comment_stmt\n\t| config_stmt\n\t| menuconfig_stmt\n\t| source_stmt\n;\n\noption_error:\n\t  T_WORD error T_EOL\t\t{ zconf_error(\"unknown option \\\"%s\\\"\", $1); }\n\t| error T_EOL\t\t\t{ zconf_error(\"invalid option\"); }\n;\n\n\n/* config/menuconfig entry */\n\nconfig_entry_start: T_CONFIG T_WORD T_EOL\n{\n\tstruct symbol *sym = sym_lookup($2, 0);\n\tsym->flags |= SYMBOL_OPTIONAL;\n\tmenu_add_entry(sym);\n\tprintd(DEBUG_PARSE, \"%s:%d:config %s\\n\", zconf_curname(), zconf_lineno(), $2);\n};\n\nconfig_stmt: config_entry_start config_option_list\n{\n\tmenu_end_entry();\n\tprintd(DEBUG_PARSE, \"%s:%d:endconfig\\n\", zconf_curname(), zconf_lineno());\n};\n\nmenuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL\n{\n\tstruct symbol *sym = sym_lookup($2, 0);\n\tsym->flags |= SYMBOL_OPTIONAL;\n\tmenu_add_entry(sym);\n\tprintd(DEBUG_PARSE, \"%s:%d:menuconfig %s\\n\", zconf_curname(), zconf_lineno(), $2);\n};\n\nmenuconfig_stmt: menuconfig_entry_start config_option_list\n{\n\tif (current_entry->prompt)\n\t\tcurrent_entry->prompt->type = P_MENU;\n\telse\n\t\tzconfprint(\"warning: menuconfig statement without prompt\");\n\tmenu_end_entry();\n\tprintd(DEBUG_PARSE, \"%s:%d:endconfig\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option_list:\n\t  /* empty */\n\t| config_option_list config_option\n\t| config_option_list symbol_option\n\t| config_option_list depends\n\t| config_option_list help\n\t| config_option_list option_error\n\t| config_option_list T_EOL\n;\n\nconfig_option: T_TYPE prompt_stmt_opt T_EOL\n{\n\tmenu_set_type($1->stype);\n\tprintd(DEBUG_PARSE, \"%s:%d:type(%u)\\n\",\n\t\tzconf_curname(), zconf_lineno(),\n\t\t$1->stype);\n};\n\nconfig_option: T_PROMPT prompt if_expr T_EOL\n{\n\tmenu_add_prompt(P_PROMPT, $2, $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:prompt\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option: T_DEFAULT expr if_expr T_EOL\n{\n\tmenu_add_expr(P_DEFAULT, $2, $3);\n\tif ($1->stype != S_UNKNOWN)\n\t\tmenu_set_type($1->stype);\n\tprintd(DEBUG_PARSE, \"%s:%d:default(%u)\\n\",\n\t\tzconf_curname(), zconf_lineno(),\n\t\t$1->stype);\n};\n\nconfig_option: T_SELECT T_WORD if_expr T_EOL\n{\n\tmenu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:select\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option: T_RANGE symbol symbol if_expr T_EOL\n{\n\tmenu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);\n\tprintd(DEBUG_PARSE, \"%s:%d:range\\n\", zconf_curname(), zconf_lineno());\n};\n\nsymbol_option: T_OPTION symbol_option_list T_EOL\n;\n\nsymbol_option_list:\n\t  /* empty */\n\t| symbol_option_list T_WORD symbol_option_arg\n{\n\tconst struct kconf_id *id = kconf_id_lookup($2, strlen($2));\n\tif (id && id->flags & TF_OPTION)\n\t\tmenu_add_option(id->token, $3);\n\telse\n\t\tzconfprint(\"warning: ignoring unknown option %s\", $2);\n\tfree($2);\n};\n\nsymbol_option_arg:\n\t  /* empty */\t\t{ $$ = NULL; }\n\t| T_EQUAL prompt\t{ $$ = $2; }\n;\n\n/* choice entry */\n\nchoice: T_CHOICE word_opt T_EOL\n{\n\tstruct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);\n\tsym->flags |= SYMBOL_AUTO;\n\tmenu_add_entry(sym);\n\tmenu_add_expr(P_CHOICE, NULL, NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:choice\\n\", zconf_curname(), zconf_lineno());\n};\n\nchoice_entry: choice choice_option_list\n{\n\t$$ = menu_add_menu();\n};\n\nchoice_end: end\n{\n\tif (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endchoice\\n\", zconf_curname(), zconf_lineno());\n\t}\n};\n\nchoice_stmt: choice_entry choice_block choice_end\n;\n\nchoice_option_list:\n\t  /* empty */\n\t| choice_option_list choice_option\n\t| choice_option_list depends\n\t| choice_option_list help\n\t| choice_option_list T_EOL\n\t| choice_option_list option_error\n;\n\nchoice_option: T_PROMPT prompt if_expr T_EOL\n{\n\tmenu_add_prompt(P_PROMPT, $2, $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:prompt\\n\", zconf_curname(), zconf_lineno());\n};\n\nchoice_option: T_TYPE prompt_stmt_opt T_EOL\n{\n\tif ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {\n\t\tmenu_set_type($1->stype);\n\t\tprintd(DEBUG_PARSE, \"%s:%d:type(%u)\\n\",\n\t\t\tzconf_curname(), zconf_lineno(),\n\t\t\t$1->stype);\n\t} else\n\t\tYYERROR;\n};\n\nchoice_option: T_OPTIONAL T_EOL\n{\n\tcurrent_entry->sym->flags |= SYMBOL_OPTIONAL;\n\tprintd(DEBUG_PARSE, \"%s:%d:optional\\n\", zconf_curname(), zconf_lineno());\n};\n\nchoice_option: T_DEFAULT T_WORD if_expr T_EOL\n{\n\tif ($1->stype == S_UNKNOWN) {\n\t\tmenu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);\n\t\tprintd(DEBUG_PARSE, \"%s:%d:default\\n\",\n\t\t\tzconf_curname(), zconf_lineno());\n\t} else\n\t\tYYERROR;\n};\n\nchoice_block:\n\t  /* empty */\n\t| choice_block common_stmt\n;\n\n/* if entry */\n\nif_entry: T_IF expr nl\n{\n\tprintd(DEBUG_PARSE, \"%s:%d:if\\n\", zconf_curname(), zconf_lineno());\n\tmenu_add_entry(NULL);\n\tmenu_add_dep($2);\n\t$$ = menu_add_menu();\n};\n\nif_end: end\n{\n\tif (zconf_endtoken($1, T_IF, T_ENDIF)) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endif\\n\", zconf_curname(), zconf_lineno());\n\t}\n};\n\nif_stmt: if_entry if_block if_end\n;\n\nif_block:\n\t  /* empty */\n\t| if_block common_stmt\n\t| if_block menu_stmt\n\t| if_block choice_stmt\n;\n\n/* mainmenu entry */\n\nmainmenu_stmt: T_MAINMENU prompt nl\n{\n\tmenu_add_prompt(P_MENU, $2, NULL);\n};\n\n/* menu entry */\n\nmenu: T_MENU prompt T_EOL\n{\n\tmenu_add_entry(NULL);\n\tmenu_add_prompt(P_MENU, $2, NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:menu\\n\", zconf_curname(), zconf_lineno());\n};\n\nmenu_entry: menu visibility_list depends_list\n{\n\t$$ = menu_add_menu();\n};\n\nmenu_end: end\n{\n\tif (zconf_endtoken($1, T_MENU, T_ENDMENU)) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endmenu\\n\", zconf_curname(), zconf_lineno());\n\t}\n};\n\nmenu_stmt: menu_entry menu_block menu_end\n;\n\nmenu_block:\n\t  /* empty */\n\t| menu_block common_stmt\n\t| menu_block menu_stmt\n\t| menu_block choice_stmt\n;\n\nsource_stmt: T_SOURCE prompt T_EOL\n{\n\tprintd(DEBUG_PARSE, \"%s:%d:source %s\\n\", zconf_curname(), zconf_lineno(), $2);\n\tzconf_nextfile($2);\n};\n\n/* comment entry */\n\ncomment: T_COMMENT prompt T_EOL\n{\n\tmenu_add_entry(NULL);\n\tmenu_add_prompt(P_COMMENT, $2, NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:comment\\n\", zconf_curname(), zconf_lineno());\n};\n\ncomment_stmt: comment depends_list\n{\n\tmenu_end_entry();\n};\n\n/* help option */\n\nhelp_start: T_HELP T_EOL\n{\n\tprintd(DEBUG_PARSE, \"%s:%d:help\\n\", zconf_curname(), zconf_lineno());\n\tzconf_starthelp();\n};\n\nhelp: help_start T_HELPTEXT\n{\n\tcurrent_entry->help = $2;\n};\n\n/* depends option */\n\ndepends_list:\n\t  /* empty */\n\t| depends_list depends\n\t| depends_list T_EOL\n\t| depends_list option_error\n;\n\ndepends: T_DEPENDS T_ON expr T_EOL\n{\n\tmenu_add_dep($3);\n\tprintd(DEBUG_PARSE, \"%s:%d:depends on\\n\", zconf_curname(), zconf_lineno());\n};\n\n/* visibility option */\n\nvisibility_list:\n\t  /* empty */\n\t| visibility_list visible\n\t| visibility_list T_EOL\n;\n\nvisible: T_VISIBLE if_expr\n{\n\tmenu_add_visibility($2);\n};\n\n/* prompt statement */\n\nprompt_stmt_opt:\n\t  /* empty */\n\t| prompt if_expr\n{\n\tmenu_add_prompt(P_PROMPT, $1, $2);\n};\n\nprompt:\t  T_WORD\n\t| T_WORD_QUOTE\n;\n\nend:\t  T_ENDMENU T_EOL\t{ $$ = $1; }\n\t| T_ENDCHOICE T_EOL\t{ $$ = $1; }\n\t| T_ENDIF T_EOL\t\t{ $$ = $1; }\n;\n\nnl:\n\t  T_EOL\n\t| nl T_EOL\n;\n\nif_expr:  /* empty */\t\t\t{ $$ = NULL; }\n\t| T_IF expr\t\t\t{ $$ = $2; }\n;\n\nexpr:\t  symbol\t\t\t\t{ $$ = expr_alloc_symbol($1); }\n\t| symbol T_EQUAL symbol\t\t\t{ $$ = expr_alloc_comp(E_EQUAL, $1, $3); }\n\t| symbol T_UNEQUAL symbol\t\t{ $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }\n\t| T_OPEN_PAREN expr T_CLOSE_PAREN\t{ $$ = $2; }\n\t| T_NOT expr\t\t\t\t{ $$ = expr_alloc_one(E_NOT, $2); }\n\t| expr T_OR expr\t\t\t{ $$ = expr_alloc_two(E_OR, $1, $3); }\n\t| expr T_AND expr\t\t\t{ $$ = expr_alloc_two(E_AND, $1, $3); }\n;\n\nsymbol:\t  T_WORD\t{ $$ = sym_lookup($1, 0); free($1); }\n\t| T_WORD_QUOTE\t{ $$ = sym_lookup($1, SYMBOL_CONST); free($1); }\n;\n\nword_opt: /* empty */\t\t\t{ $$ = NULL; }\n\t| T_WORD\n\n%%\n\nvoid conf_parse(const char *name)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tzconf_initscan(name);\n\n\tsym_init();\n\t_menu_init();\n\trootmenu.prompt = menu_add_prompt(P_MENU, \"Linux Kernel Configuration\", NULL);\n\n\tif (getenv(\"ZCONF_DEBUG\"))\n\t\tzconfdebug = 1;\n\tzconfparse();\n\tif (zconfnerrs)\n\t\texit(1);\n\tif (!modules_sym)\n\t\tmodules_sym = sym_find( \"n\" );\n\n\trootmenu.prompt->text = _(rootmenu.prompt->text);\n\trootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);\n\n\tmenu_finalize(&rootmenu);\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_check_deps(sym))\n\t\t\tzconfnerrs++;\n        }\n\tif (zconfnerrs)\n\t\texit(1);\n\tsym_set_change_count(1);\n}\n\nstatic const char *zconf_tokenname(int token)\n{\n\tswitch (token) {\n\tcase T_MENU:\t\treturn \"menu\";\n\tcase T_ENDMENU:\t\treturn \"endmenu\";\n\tcase T_CHOICE:\t\treturn \"choice\";\n\tcase T_ENDCHOICE:\treturn \"endchoice\";\n\tcase T_IF:\t\treturn \"if\";\n\tcase T_ENDIF:\t\treturn \"endif\";\n\tcase T_DEPENDS:\t\treturn \"depends\";\n\tcase T_VISIBLE:\t\treturn \"visible\";\n\t}\n\treturn \"<token>\";\n}\n\nstatic bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)\n{\n\tif (id->token != endtoken) {\n\t\tzconf_error(\"unexpected '%s' within %s block\",\n\t\t\tkconf_id_strings + id->name, zconf_tokenname(starttoken));\n\t\tzconfnerrs++;\n\t\treturn false;\n\t}\n\tif (current_menu->file != current_file) {\n\t\tzconf_error(\"'%s' in different file than '%s'\",\n\t\t\tkconf_id_strings + id->name, zconf_tokenname(starttoken));\n\t\tfprintf(stderr, \"%s:%d: location of the '%s'\\n\",\n\t\t\tcurrent_menu->file->name, current_menu->lineno,\n\t\t\tzconf_tokenname(starttoken));\n\t\tzconfnerrs++;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nstatic void zconfprint(const char *err, ...)\n{\n\tva_list ap;\n\n\tfprintf(stderr, \"%s:%d: \", zconf_curname(), zconf_lineno());\n\tva_start(ap, err);\n\tvfprintf(stderr, err, ap);\n\tva_end(ap);\n\tfprintf(stderr, \"\\n\");\n}\n\nstatic void zconf_error(const char *err, ...)\n{\n\tva_list ap;\n\n\tzconfnerrs++;\n\tfprintf(stderr, \"%s:%d: \", zconf_curname(), zconf_lineno());\n\tva_start(ap, err);\n\tvfprintf(stderr, err, ap);\n\tva_end(ap);\n\tfprintf(stderr, \"\\n\");\n}\n\nstatic void zconferror(const char *err)\n{\n\tfprintf(stderr, \"%s:%d: %s\\n\", zconf_curname(), zconf_lineno() + 1, err);\n}\n\nstatic void print_quoted_string(FILE *out, const char *str)\n{\n\tconst char *p;\n\tint len;\n\n\tputc('\"', out);\n\twhile ((p = strchr(str, '\"'))) {\n\t\tlen = p - str;\n\t\tif (len)\n\t\t\tfprintf(out, \"%.*s\", len, str);\n\t\tfputs(\"\\\\\\\"\", out);\n\t\tstr = p + 1;\n\t}\n\tfputs(str, out);\n\tputc('\"', out);\n}\n\nstatic void print_symbol(FILE *out, struct menu *menu)\n{\n\tstruct symbol *sym = menu->sym;\n\tstruct property *prop;\n\n\tif (sym_is_choice(sym))\n\t\tfprintf(out, \"\\nchoice\\n\");\n\telse\n\t\tfprintf(out, \"\\nconfig %s\\n\", sym->name);\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\t\tfputs(\"  boolean\\n\", out);\n\t\tbreak;\n\tcase S_TRISTATE:\n\t\tfputs(\"  tristate\\n\", out);\n\t\tbreak;\n\tcase S_STRING:\n\t\tfputs(\"  string\\n\", out);\n\t\tbreak;\n\tcase S_INT:\n\t\tfputs(\"  integer\\n\", out);\n\t\tbreak;\n\tcase S_HEX:\n\t\tfputs(\"  hex\\n\", out);\n\t\tbreak;\n\tdefault:\n\t\tfputs(\"  ???\\n\", out);\n\t\tbreak;\n\t}\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tif (prop->menu != menu)\n\t\t\tcontinue;\n\t\tswitch (prop->type) {\n\t\tcase P_PROMPT:\n\t\t\tfputs(\"  prompt \", out);\n\t\t\tprint_quoted_string(out, prop->text);\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\" if \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t}\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_DEFAULT:\n\t\t\tfputs( \"  default \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\" if \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t}\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_CHOICE:\n\t\t\tfputs(\"  #choice value\\n\", out);\n\t\t\tbreak;\n\t\tcase P_SELECT:\n\t\t\tfputs( \"  select \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_RANGE:\n\t\t\tfputs( \"  range \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_MENU:\n\t\t\tfputs( \"  menu \", out);\n\t\t\tprint_quoted_string(out, prop->text);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfprintf(out, \"  unknown prop %d!\\n\", prop->type);\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (menu->help) {\n\t\tint len = strlen(menu->help);\n\t\twhile (menu->help[--len] == '\\n')\n\t\t\tmenu->help[len] = 0;\n\t\tfprintf(out, \"  help\\n%s\\n\", menu->help);\n\t}\n}\n\nvoid zconfdump(FILE *out)\n{\n\tstruct property *prop;\n\tstruct symbol *sym;\n\tstruct menu *menu;\n\n\tmenu = rootmenu.list;\n\twhile (menu) {\n\t\tif ((sym = menu->sym))\n\t\t\tprint_symbol(out, menu);\n\t\telse if ((prop = menu->prompt)) {\n\t\t\tswitch (prop->type) {\n\t\t\tcase P_COMMENT:\n\t\t\t\tfputs(\"\\ncomment \", out);\n\t\t\t\tprint_quoted_string(out, prop->text);\n\t\t\t\tfputs(\"\\n\", out);\n\t\t\t\tbreak;\n\t\t\tcase P_MENU:\n\t\t\t\tfputs(\"\\nmenu \", out);\n\t\t\t\tprint_quoted_string(out, prop->text);\n\t\t\t\tfputs(\"\\n\", out);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t;\n\t\t\t}\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\"  depends \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t\tfputc('\\n', out);\n\t\t\t}\n\t\t}\n\n\t\tif (menu->list)\n\t\t\tmenu = menu->list;\n\t\telse if (menu->next)\n\t\t\tmenu = menu->next;\n\t\telse while ((menu = menu->parent)) {\n\t\t\tif (menu->prompt && menu->prompt->type == P_MENU)\n\t\t\t\tfputs(\"\\nendmenu\\n\", out);\n\t\t\tif (menu->next) {\n\t\t\t\tmenu = menu->next;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#include \"zconf.lex.c\"\n#include \"util.c\"\n#include \"confdata.c\"\n#include \"expr.c\"\n#include \"symbol.c\"\n#include \"menu.c\"\n"
  },
  {
    "path": "kernel/Kconfig",
    "content": "menu \"Compiler options\"\n    config GDB_CFLAG\n    bool \"Keep debugging symbols\"\n    default y\n\n    choice\n    prompt \"Compiler optimization\"\n        config OPTIMIZE_NONE\n        bool \"No optimization\"\n\n        config OPTIMIZE_SIZE\n        bool \"Optimize for size\"\n\n        config OPTIMIZE_PERF\n        bool \"Optimize for performance\"\n    endchoice\n\n\nendmenu\n\n\nmenu \"Platform Selection\"\n\n    choice ARCH\n        prompt \"Architecture\"\n        default ARCH_LM3S\n\n        config ARCH_LM3S\n        bool \"LM3S\"\n        help\n            Enable support for Stellaris LM3S systems\n\n        config ARCH_LPC17XX\n        bool \"LPC17XX\"\n        help\n            Enable support for NXP LPC17xx systems\n\n        config ARCH_STM32F4\n        bool \"STM32F4\"\n        help\n            Enable support for ST STM32F4 systems\n\n        config ARCH_STM32F7\n        bool \"STM32F7\"\n        help\n            Enable support for ST STM32F7 systems\n\n        config ARCH_NRF51\n        bool \"NRF51\"\n        help\n            Enable support for Nordic NRF51 systems\n\n        config ARCH_NRF52\n        bool \"NRF52\"\n        help\n            Enable support for Nordic NRF52 systems\n    endchoice\n\n\n    source \"../kernel/stm32f7/Kconfig\"\n    source \"../kernel/stm32f4/Kconfig\"\n    source \"../kernel/lpc17xx/Kconfig\"\n    source \"../kernel/lm3s/Kconfig\"\n    source \"../kernel/nrf51/Kconfig\"\n    source \"../kernel/nrf52/Kconfig\"\n\n    config FLASH_SIZE_2MB\n            bool\n    config FLASH_SIZE_1MB\n            bool\n    config FLASH_SIZE_512KB\n            bool\n    config FLASH_SIZE_384KB\n            bool\n    config FLASH_SIZE_256KB\n            bool\n    config FLASH_SIZE_192KB\n            bool\n    config FLASH_SIZE_128KB\n            bool\n\n    config RAM_SIZE_368KB\n            bool\n    config RAM_SIZE_320KB\n            bool\n    config RAM_SIZE_256KB\n            bool\n    config RAM_SIZE_192KB\n            bool\n    config RAM_SIZE_128KB\n            bool\n    config RAM_SIZE_96KB\n            bool\n    config RAM_SIZE_64KB\n            bool\n    config RAM_SIZE_32KB\n            bool\n    config RAM_SIZE_24KB\n            bool\n    config RAM_SIZE_16KB\n            bool\n\n    config ARCH_STM32F401\n        bool\n    config ARCH_STM32F405\n        bool\n    config ARCH_STM32F407\n        bool\n    config ARCH_STM32F411\n        bool\n    config ARCH_STM32F429\n        bool\n    config ARCH_STM32F446\n        bool\n    config ARCH_STM32F746\n        bool\n    config ARCH_STM32F769\n        bool\n\n    config DEVSTM32DMA\n        bool\n\n    #Temp hack to allow '407 & '411 clock setups to coexist\n    choice\n        prompt \"Clock Speed\"\n        config CLK_16MHZ\n            bool \"16MHz\"\n            depends on (ARCH_NRF51)\n        config CLK_48MHZ\n            bool \"48MHz\"\n            depends on (ARCH_STM32F401  || ARCH_STM32F411 || ARCH_STM32F429) || ARCH_STM32F407 || ARCH_STM32F405\n        config CLK_84MHZ\n            bool \"84MHz\"\n            depends on (ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F429 || ARCH_NRF52) || ARCH_STM32F407 || ARCH_STM32F405\n        config CLK_100MHZ\n            bool \"100MHz\"\n            depends on ARCH_LPC17XX || ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405\n        config CLK_120MHZ\n            bool \"120MHz\"\n            depends on (ARCH_STM32F407 || ARCH_STM32F405 || ARCH_LPC1769)\n        config CLK_168MHZ\n            bool \"168MHz\"\n            depends on (ARCH_STM32F407 ||  ARCH_STM32F405 || ARCH_STM32F429)\n        config CLK_180MHZ\n            bool \"180MHz\"\n            depends on (ARCH_STM32F446)\n        config CLK_216MHZ\n            bool \"216MHZ\"\n            depends on (ARCH_STM32F746 || ARCH_STM32F769)\n    endchoice\n\n    choice\n        prompt \"Board\"\n        default MACH_STM32F407Discovery\n    config MACH_STM32F746Discovery\n        bool \"STM32F746 Discovery\"\n        depends on (ARCH_STM32F746)\n    config MACH_STM32F769Discovery\n        bool \"STM32F769 Discovery\"\n        depends on (ARCH_STM32F769)\n    config MACH_STM32F746Nucleo144\n        bool \"STM32F746 Nucleo-144\"\n        depends on (ARCH_STM32F746)\n    config MACH_STM32F407Discovery\n        bool \"STM32F407Discovery\"\n        depends on (ARCH_STM32F407)\n    config MACH_STM32F405Pyboard10\n        bool \"STM32F405 PyBoard v1.0 (micropython)\"\n        depends on (ARCH_STM32F405)\n    config MACH_STM32F405Pyboard11\n        bool \"STM32F405 PyBoard v1.1 (micropython)\"\n        depends on (ARCH_STM32F405)\n    config MACH_STM32F411Pyboard11lite\n        bool \"STM32F411 PyBoard v1.1 lite (micropython)\"\n        depends on (ARCH_STM32F411)\n    config MACH_STM32F4x1Discovery\n        bool \"STM32F4x1Discovery\"\n        depends on (   ARCH_STM32F401 ||ARCH_STM32F411)\n    config MACH_STM32F429Discovery\n        bool \"STM32F429Discovery\"\n        depends on (ARCH_STM32F429)\n    config MACH_STM32F446Nucleo\n        bool \"STM32F446 Nucleo\"\n        depends on (ARCH_STM32F446)\n    config MACH_STM32F411Nucleo\n        bool \"STM32F411 Nucleo\"\n        depends on (ARCH_STM32F411)\n    config MACH_STM32F407Diymore\n        bool \"STM32F407 based Diymore from dyimore.cc\"\n        depends on (ARCH_STM32F407)\n    config MACH_LPC1768MBED\n        bool \"LPC1768MBED\"\n        depends on ARCH_LPC1768\n    config MACH_SEEEDPRO\n        bool \"SEEEDPRO\"\n        depends on ARCH_LPC1768\n    config MACH_LPC1679XPRESSO\n        bool \"LPC1679XPRESSO\"\n        depends on ARCH_LPC1769\n    config MACH_LM3S6965EVB\n        bool \"lm3s6965evb\"\n        depends on ARCH_LM3S6965\n    config MACH_LM3SVIRT\n        bool \"lm3s-qemu\"\n        depends on ARCH_LM3SVIRT\n        default y\n    config MACH_BLENANOV1_5\n        bool \"BLENanoV1.5\"\n        depends on ARCH_NRF51\n        default y\n    config MACH_BLENANOV2_0\n        bool \"BLENanoV2.0\"\n        depends on ARCH_NRF52\n        default y\n\n    endchoice\n\n    config STM32F7_SDRAM\n    depends on ARCH_STM32F7\n    bool \"Enable external SDRAM\"\n    default y\n\n    config STM32F4_SDRAM\n    depends on ARCH_STM32F4\n    bool \"Enable external SDRAM\"\n    default n\n\nendmenu\n\n\nmenu \"Kernel Configuration\"\n\nconfig KFLASHMEM_SIZE\n    int \"Kernel Flash size (KB)\"\n    default 64\n\nconfig KRAMMEM_SIZE\n    int \"Kernel RAM size (KB)\"\n    default 64\n\nchoice\nprompt \"Tasks Stack Size\"\ndefault TASK_STACK_SIZE_2K\n\n   config TASK_STACK_SIZE_1K\n   bool \"Tiny stack (1024 Bytes)\"\n\n   config TASK_STACK_SIZE_2K\n   bool \"Small stack (2048 Bytes)\"\n\n   config TASK_STACK_SIZE_4K\n   bool \"Big stack (4096 Bytes)\"\n\n   config TASK_STACK_SIZE_8K\n   bool \"Huge stack (8192 Bytes)\"\nendchoice\n\nconfig MPU\nbool \"Run-time Memory Protection\"\ndefault y\n\nconfig PTHREADS\nbool \"POSIX Threads (pthreads)\"\ndefault y\n\nconfig SIGNALS\nbool \"Process Signals\"\ndefault y\n\nconfig PIPE\nbool \"Pipe\"\ndefault y\n\nconfig SOCK_UNIX\nbool \"UNIX Sockets for IPC\"\ndefault n\n\nconfig PTY_UNIX\nbool \"UNIX98 scheme pseudo-tty devices (/dev/pts/X)\"\ndefault n\n\nendmenu\n\n\n\nmenu \"Debugging options\"\n\nconfig KLOG\n    bool \"Enable kernel logging\"\n    default y\n\nconfig KLOG_SIZE\n    depends on KLOG\n    int \"Kernel log buffer size\"\n    default 256\n\nconfig MEMFAULT_DBG\n    bool \"Enable extended segfault debug\"\n    default y\n\nconfig HARDFAULT_DBG\n    bool \"Enable extended hardfault debug\"\n    default n\n\nconfig STRACE\n    bool \"Enable syscall tracer\"\n    default n\n\nendmenu\n\n\nmenu \"Filesystems\"\n       config SYSFS\n       bool \"SysFS (/sys)\"\n       default y\n\n       config MEMFS\n       bool \"MemFS\"\n       default y\n\n       config XIPFS\n       bool \"Xip FS\"\n       default y\n\n       config FATFS\n       bool \"Fat FS\"\n       default n\n\n       config FAT32\n       depends on FATFS\n       bool \"Fat32 support\"\n       default n\n\nendmenu\n\nmenu \"Networking\"\n       config SOCK_INET\n       bool \"TCP/IP Socket support\"\n       default n\n       config TCPIP_MEMPOOL_YN\n       bool \"Separate memory pool for TCP/IP stack\"\n       default n\n       if TCPIP_MEMPOOL_YN\n        config TCPIP_MEMPOOL\n        string \"TCP/IP pool base address\"\n        default \"0x10000000\"\n       endif\n       choice NET_STACK\n        prompt \"TCP/IP stack selection\"\n        default PICOTCP\n        depends on SOCK_INET\n\n        config PICOTCP\n        bool \"Built-in PicoTCP\"\n       endchoice\n       source ../kernel/net/Kconfig\n\nendmenu\n\nmenu \"Device Drivers\"\n       config DEVNULL\n       bool \"Support for /dev/null and /dev/zero\"\n       default y\n\n       menuconfig DEVUART\n       bool \"Generic UART driver\"\n       default y\n\n       if DEVUART\n\n            config USART_0\n            bool \"USART 0\"\n            depends on (ARCH_LM3S6965 || ARCH_LM3SVIRT)\n\n            config USART_1\n            bool \"USART 1\"\n            depends on (ARCH_LM3S6965 || ARCH_LM3SVIRT || \\\n                        ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F405 || ARCH_STM32F407  || ARCH_STM32F429 || ARCH_STM32F446 || \\\n                        ARCH_STM32F746 || ARCH_STM32F769)\n\n            config USART_2\n            bool \"USART 2\"\n            depends on (ARCH_LM3S6965 || ARCH_LM3SVIRT || \\\n                        ARCH_STM32F401 || ARCH_STM32F411 || ARCH_STM32F405 || ARCH_STM32F429  || ARCH_STM32F407 || ARCH_STM32F446 || \\\n                        ARCH_STM32F746 || ARCH_STM32F769 )\n\n            config USART_3\n            bool \"USART 3\"\n            depends on (ARCH_STM32F407 || ARCH_STM32F405 || ARCH_STM32F746 || ARCH_STM32F769 )\n\n            config USART_4\n            bool \"USART 4\"\n            depends on (ARCH_STM32F405)\n\n            config USART_6\n            bool \"USART 6\"\n            depends on (ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405 || ARCH_STM32F446 || \\\n                        ARCH_STM32F746 || ARCH_STM32F769 )\n\n            config UART_0\n            bool \"UART 0\"\n            depends on (ARCH_LPC17XX || ARCH_NRF51 || ARCH_NRF52)\n\n            config UART_1\n            bool \"UART 1\"\n            depends on ARCH_LPC17XX\n\n            config UART_2\n            bool \"UART 2\"\n            depends on ARCH_LPC17XX\n\n            config UART_3\n            bool \"UART 3\"\n            depends on ARCH_LPC17XX\n\n       endif\n\n       config DEVF4DSP\n       bool \"STM32F4 Sound driver\"\n       depends on (ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405  || ARCH_STM32F429 || ARCH_STM32F446)\n       select DEVSTM32DMA\n       default n\n\n       config DEVSTM32USB\n       bool\n\n       menuconfig DEVSTM32USBFS\n       bool \"Support for Full Speed USB OTG\"\n       depends on (!DEVSTM32USBHFS) && (ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405  || ARCH_STM32F429 || ARCH_STM32F446 || \\\n                   ARCH_STM32F746)\n       default n\n       select DEVSTM32USB\n       if DEVSTM32USBFS\n          choice\n            prompt \"USB FS OTG mode\"\n            default USBFS_GUEST\n            config USBFS_HOST\n            bool \"Host mode\"\n\n            config USBFS_GUEST\n            bool \"Device mode\"\n\n          endchoice\n       endif\n\n       menuconfig DEVSTM32USBHS\n       bool \"Support for High Speed USB OTG\"\n       depends on (ARCH_STM32F746 || ARCH_STM32F769)\n       select DEVSTM32USB\n       default n\n       if DEVSTM32USBHS\n          choice\n            prompt \"USB HS OTG mode\"\n            default USBHS_GUEST\n            config USBHS_HOST\n            bool \"Host mode\"\n\n            config USBHS_GUEST\n            bool \"Device mode\"\n\n          endchoice\n\n        endif\n\n      config DEV_USB_ETH\n      depends on PICOTCP && ( (DEVSTM32USBHS && USBHS_GUEST) || (DEVSTM32USBFS && USBFS_GUEST) )\n      select DEVSTM32USB\n      bool \"Ethernet over USB (CDC-ECM)\"\n      default n\n\n      config DEV_USBH_KBD\n      depends on (USBHS_HOST || USBFS_HOST)\n      bool \"USB Keyboard support\"\n      default n\n\n      if DEV_USB_ETH\n      config USB_DEFAULT_IP\n      string \"Default (boot-up) address for usb0\"\n      default 192.168.6.150\n\n      config USB_DEFAULT_NM\n      string \"Default (boot-up) netmask for usb0\"\n      default 255.255.255.0\n\n      config USB_DEFAULT_GW\n      string \"Default (boot-up) gateway for usb0\"\n      default 192.168.6.1\n      endif\n\n       config DEVADC\n       bool \"Generic ADC driver\"\n       depends on (ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405  || ARCH_STM32F429 || ARCH_STM32F446)\n       select DEVSTM32DMA\n       default n\n\n\n       config DEVF4ETH\n       bool \"STM32F4 Ethernet driver\"\n       depends on ((ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405  || ARCH_STM32F429 || ARCH_STM32F446) && PICOTCP)\n       default n\n\n       config DEVF7ETH\n       bool \"STM32F7 Ethernet driver\"\n       depends on ((ARCH_STM32F746 || ARCH_STM32F769) && PICOTCP)\n       default n\n\n       config DEVLM3SETH\n       bool \"LM3S Ethernet driver\"\n       depends on ((ARCH_LM3S) && PICOTCP)\n       default n\n\n       if DEVF4ETH || DEVF7ETH || DEVLM3SETH\n               config ETH_DEFAULT_IP\n               string \"Default (boot-up) address for eth0\"\n               default 192.168.2.150\n\n               config ETH_DEFAULT_NM\n               string \"Default (boot-up) netmask for eth0\"\n               default 255.255.255.0\n\n               config ETH_DEFAULT_GW\n               string \"Default (boot-up) gateway for eth0\"\n               default 192.168.2.1\n\n       endif\n\n       config DEVSTM32SDIO\n       bool \"STM32F4/7 SD I/O driver\"\n       depends on (ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405  || ARCH_STM32F429 || ARCH_STM32F7|| ARCH_STM32F446)\n       default n\n\n       menuconfig DEVSTM32I2C\n       bool \"STM32 I2C driver\"\n       depends on (ARCH_STM32F401 ||ARCH_STM32F411 || ARCH_STM32F407 || ARCH_STM32F405  || ARCH_STM32F429 || ARCH_STM32F446 || ARCH_STM32F746)\n       select DEVSTM32DMA\n       default n\n\n\n           if DEVSTM32I2C\n                config I2C1\n                bool \"I2C 1\"\n                default n\n                config I2C2\n                bool \"I2C 2\"\n                default n\n                config I2C3\n                bool \"I2C 3\"\n                default y\n           endif\n\n           config DEVCS43L22\n           tristate \"CS43L22 driver (Stereo DAC)\"\n           depends on (DEVSTM32I2C)\n           default n\n\n\n           config DEVLSM303DLHC\n           tristate \"LSM303DLHC driver (Accelerometer & Magnetometer)\"\n           depends on (DEVSTM32I2C)\n           default n\n\n           config DEVMCCOG21\n           tristate \"MCCOG21 driver (2-lines B/W display)\"\n           depends on (DEVSTM32I2C)\n           default n\n\n           config DEVXALED5X7\n           tristate \"Xadow LED Matrix 5X7 driver\"\n           depends on (DEVSTM32I2C)\n           default n\n\n           config DEVFT5336\n           tristate \"FT5336 driver (Touchscreen STM32F746)\"\n           depends on (DEVSTM32I2C)\n           default n\n\n           config DEVSTMPE811\n           tristate \"STMPE811 driver (Touchscreen)\"\n           depends on (DEVSTM32I2C)\n           default n\n\n\n\n       menuconfig DEVSPI\n           bool \"Generic SPI driver\"\n           depends on (ARCH_STM32F4 || ARCH_STM32F7)\n           select DEVSTM32DMA\n           default n\n\n           if DEVSPI\n                config SPI_1\n                bool \"SPI 1\"\n\n                config SPI_3\n                bool \"SPI 3\"\n\n                config SPI_5\n                bool \"SPI 5\"\n\n           endif\n\n           config DEVLIS3DSH\n           tristate \"LIS3DSH driver (3-Axis Accelerometer)\"\n           depends on (DEVSPI)\n           default n\n\n           config DEVILI9341\n           tristate \"ILI9341 driver (LCD Controller)\"\n           depends on (DEVSPI)\n           default n\n\n           config DEVL3GD20\n           tristate \"L3GD20 driver (Gyro)\"\n           depends on (DEVSPI)\n           default n\n\n       config DEV_RANDOM\n       depends on (ARCH_STM32F4 || ARCH_STM32F7)\n       bool \"STM32F2/F4/F7 Random devices\"\n       default n\n\n       if DEV_RANDOM\n          choice\n            prompt \"Random device selection\"\n            config DEVRNG\n            bool \"Hardware TRNG driver\"\n\n            config DEVFRAND\n            bool \"Fortuna PRNG device\"\n          endchoice\n       endif\n\n       menuconfig DEVFRAMEBUFFER\n           depends on (ARCH_STM32F7 || ARCH_STM32F4)\n           bool \"STM32 Framebuffer driver\"\n           default y\n\n       config DEVFBCON\n           depends on DEVFRAMEBUFFER\n           bool \"Console on Framebuffer via /dev/fbcon\"\n           default y\n        choice FONT_FACE\n            prompt \"Console font face\"\n            depends on DEVFBCON\n            default FONT_CGA8X8\n\n            config FONT_CGA_8X8\n            bool \"CGA 8x8\"\n\n            config FONT_PICCOLO_7X6\n            bool \"Piccolo 7x6\"\n        endchoice\n\n\n       config DEVF7DISCOLTDC\n           depends on DEVFRAMEBUFFER\n           bool \"F746 Discovery LTDC\"\n           default y\n\nendmenu\n\nmenu \"Power Management\"\n    config LOWPOWER\n    bool \"Enable suspend() and standby() syscalls\"\n    default n\n    config LSE32K\n    depends on LOWPOWER\n    bool \"Use external low-speed oscillator (LSE) at 32kHz to feed the RTC\"\n    default n\nendmenu\n"
  },
  {
    "path": "kernel/adc.h",
    "content": "#ifndef INC_ADC\n#define INC_ADC\n\n#define NUM_ADC_CHANNELS    16\n\nstruct adc_config {\n    uint32_t base;\n    uint32_t irq;\n    uint32_t rcc;\n    const char * name;\n    uint8_t channel_array[NUM_ADC_CHANNELS];\n    uint8_t num_channels;\n\n    struct dma_config dma;\n    uint32_t dma_rcc;\n};\n\nvoid adc_init(const struct adc_config adc_configs[], int num_adc);\n\n#endif\n\n"
  },
  {
    "path": "kernel/bflt.c",
    "content": "/*  \n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as \n *      published by the free Software Foundation.\n *      \n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */  \n#include \"frosted.h\"\n#include \"flat.h\"\n#include \"kprintf.h\"\n#include \"libopencmsis/core_cm3.h\"\n#include \"unicore-mx/cm3/systick.h\"\n\n/*************************\n * bFLT start \n *************************/\n#define RELOC_FAILED 0xff00ff01     /* Relocation incorrect somewhere */\n\nstatic inline uint16_t short_be(uint16_t le)\n{\n    return (uint16_t)(((le & 0xFFu) << 8) | ((le >> 8u) & 0xFFu));\n}\n\nstatic inline uint32_t long_be(uint32_t le)\n{\n    uint8_t *b = (uint8_t *)&le;\n    uint32_t be = 0;\n    uint32_t b0, b1, b2;\n    b0 = b[0];\n    b1 = b[1];\n    b2 = b[2];\n    be = b[3] + (b2 << 8) + (b1 << 16) + (b0 << 24);\n    return be;\n}\n\nstatic void load_header(struct flat_hdr * to_hdr, struct flat_hdr * from_hdr) {\n    memcpy((uint8_t*)to_hdr, (uint8_t*)from_hdr, sizeof(struct flat_hdr));\n}\n\nstatic int check_header(struct flat_hdr * header) {\n    if (memcmp(header->magic, \"bFLT\", 4) != 0) {\n        kprintf(\"bFLT: Magic number does not match\\r\\n\");\n        return -1;\n    }\n    if (long_be(header->rev) != FLAT_VERSION){\n        kprintf(\"bFLT: Version number does not match\\r\\n\");\n        return -1;\n    }\n\n    /* check for unsupported flags */\n    if (long_be(header->flags) & (FLAT_FLAG_GZIP | FLAT_FLAG_GZDATA)) {\n        kprintf(\"bFLT: Unsupported flags detected - GZip'd data is not supported\\r\\n\");\n        return -1;\n    }\n    return 0;\n}\n\nstatic unsigned long * calc_reloc(uint8_t * base, uint32_t offset)\n{\n    /* the library id is in top byte of offset */\n    int id = (offset >> 24) & 0x000000FFu;\n    if (id)\n    {\n        kprintf(\"bFLT: No shared library support\\r\\n\");\n        return (unsigned long *)RELOC_FAILED;\n    }\n    return (unsigned long *)(base + (offset & 0x00FFFFFFu));\n}\n\nstatic int process_got_relocs(struct flat_hdr * hdr, uint8_t * base, uint8_t * got_start)\n{\n    /*\n     * Addresses in header are relative to start of FILE (so including flat_hdr)\n     * Addresses in the relocs are relative to start of .text (so excluding flat_hdr)\n     */\n    unsigned long * rp = (unsigned long * )got_start;\n    unsigned long data_start = long_be(hdr->data_start) - sizeof(struct flat_hdr);\n    unsigned long bss_end = long_be(hdr->bss_end) - sizeof(struct flat_hdr);\n    uint8_t * text_start_dest = base + sizeof(struct flat_hdr);\n    uint8_t * data_start_dest = got_start;\n\n    for (rp; *rp != 0xffffffff; rp++) {\n        if (*rp) {\n            unsigned long addr = RELOC_FAILED;\n            if (*rp < data_start) {\n                /* reloc is in .text section: BASE == text_start  -- addr == relative to .text */\n                addr = (unsigned long)calc_reloc(text_start_dest, *rp);\n            } else if (*rp < bss_end) {\n                /* reloc is in .data section: BASE == data_start  -- addr == relative to .text - (start of data) */\n                addr = (unsigned long)calc_reloc(data_start_dest, *rp - data_start);\n            }\n\n            /* this will remap pointers starting from address 0x0, to wherever they are actually loaded in the memory map (.text reloc) */\n            if (addr == RELOC_FAILED) {\n                //errno = -ENOEXEC;\n                return -1;\n            }\n            *rp = addr;\n        }\n    }\n    return 0;\n}\n\n/* works only for FLAT v4 */\n/* reloc starts just after data_end */\nint process_relocs(struct flat_hdr * hdr, unsigned long * base, unsigned long data_start_dest,  unsigned long *reloc, int relocs)\n{\n    int i;\n    /* Relocations in the table point to an address,\n     * at that address(1), there is an adress(2) that needs fixup,\n     * and needs to be written at it's original address(1), after it's been fixed\n     */\n    /*\n     * Addresses in header are relative to start of FILE (so including flat_hdr)\n     * Addresses in the relocs are relative to start of .text (so excluding flat_hdr)\n     */\n    unsigned long data_start = long_be(hdr->data_start) - sizeof(struct flat_hdr);\n    unsigned long data_end = long_be(hdr->data_end) - sizeof(struct flat_hdr); /* relocs must be located in .data segment for GOTPIC */\n    unsigned long bss_end = long_be(hdr->bss_end) - sizeof(struct flat_hdr);\n    unsigned long text_start_dest = ((unsigned long)base) + sizeof(struct flat_hdr); /* original RELOC is relative to text_start (.bss in ROM/Flash/source) */\n    /*\n     * Now run through the relocation entries.\n     * We've got to be careful here as C++ produces relocatable zero\n     * entries in the constructor and destructor tables which are then\n     * tested for being not zero (which will always occur unless we're\n     * based from address zero).  This causes an endless loop as __start\n     * is at zero.  The solution used is to not relocate zero addresses.\n     * This has the negative side effect of not allowing a global data\n     * reference to be statically initialised to _stext (I've moved\n     * __start to address 4 so that is okay).\n     */\n    for (i=0; i < relocs; i++) {\n        unsigned long addr, *fixup_addr;\n        unsigned long *relocd_addr = (unsigned long *)RELOC_FAILED;\n        \n        /* Get the address of the pointer to be\n           relocated (of course, the address has to be\n           relocated first).  */\n        fixup_addr = (unsigned long *)long_be(reloc[i]);\n        /* two cases: reloc_addr < text_end: For now we only support GOTPIC, which cannot have relocations in .text segment!\n         *        or  reloc_addr > data_start\n         */\n        /* TODO: Make common between GOT and regular relocs ? */\n\n\n\n        if ((unsigned long)fixup_addr < data_start)\n        {\n            /* FAIL -- non GOTPIC, cannot write to ROM/.text */\n            return -1;\n        } else if ((unsigned long)fixup_addr < data_end) {\n            /* Reloc is in .data section (must be for GOTPIC), now make this point to the .data source (in the DEST ram!), and dereference */\n            fixup_addr = (unsigned long *)calc_reloc((uint8_t *)((unsigned long)data_start_dest - (unsigned long)data_start), (unsigned long)fixup_addr);\n            if (fixup_addr == (unsigned long *)RELOC_FAILED)\n                return -1;\n\n            /* Again 2 cases: reloc points to .text -- or to .data/.bss */\n            if (*fixup_addr < data_start) {\n                /* reloc is in .text section: BASE == text_start  -- addr == relative to .text */\n                relocd_addr = (unsigned long *)calc_reloc((uint8_t *)text_start_dest, *fixup_addr);\n            } else if (*fixup_addr < bss_end) {\n                /* reloc is in .data section: BASE == data_start  -- addr == relative to .text - (start of data) */\n                relocd_addr = (unsigned long *)calc_reloc((uint8_t *)data_start_dest, *fixup_addr - data_start);\n            } else {\n                relocd_addr = (unsigned long *)RELOC_FAILED;\n                return -1;\n            }\n            /* write the relocated/offsetted value back were it was read */\n            *fixup_addr = (unsigned long)relocd_addr;\n        }\n\n        if (relocd_addr == (unsigned long *)RELOC_FAILED) {\n            kprintf(\"bFLT: Unable to calculate relocation address\\r\\n\");\n            return -1;\n        }\n\n    }\n\n    return 0;\n}\n\n\n/* BFLT file structure:\n *\n * +------------------------+   0x0\n * | BFLT header            |\n * +------------------------+\n * | padding                |\n * +------------------------+   entry\n * | .text section          |\n * |                        |\n * +------------------------+   data_start\n * | .data section          |\n * |                        |   \n * +------------------------+   data_end, relocs_start, bss_start\n * | relocations (and .bss) |\n * |........................|   relocs_end   <- BFLT ends here\n * | (.bss section)         |\n * +------------------------+   bss_end\n */\n\nint bflt_load(uint8_t* from, void **reloc_text, void **reloc_data, void **reloc_bss,\n              void ** entry_point, size_t *stack_size, uint32_t *got_loc, uint32_t *text_len, uint32_t *data_len)\n{\n    struct flat_hdr hdr;\n    void * mem = NULL;\n    uint32_t bss_len, stack_len, flags, alloc_len, entry_point_offset;\n    uint8_t *relocs_src, *text_src, *data_dest;\n    uint8_t *address_zero = from;\n    int32_t relocs, rev;\n\n    //kprintf(\"bFLT: Loading from 0x%p\\r\\n\", from);\n\n    if (!address_zero) {\n        goto error;\n    }\n\n    load_header(&hdr, (struct flat_hdr *)address_zero);\n    if (check_header(&hdr) != 0) {\n        kprintf(\"bFLT: Bad FLT header\\r\\n\");\n        goto error;\n    }\n\n    /* Calculate all the sizes */\n    *text_len           = long_be(hdr.data_start) - sizeof(struct flat_hdr);\n    *data_len           = long_be(hdr.data_end) - long_be(hdr.data_start);\n    bss_len             = long_be(hdr.bss_end) - long_be(hdr.data_end);\n    stack_len           = long_be(hdr.stack_size);\n    relocs              = long_be(hdr.reloc_count);\n    flags               = long_be(hdr.flags);\n    rev                 = long_be(hdr.rev);\n    /* Calculate source addresses */\n    text_src            = address_zero + sizeof(struct flat_hdr);\n    relocs_src          = address_zero + long_be(hdr.reloc_start);\n    entry_point_offset  = (long_be(hdr.entry) & 0xFFFFFFFE) - sizeof(struct flat_hdr); /* offset inside .text + reset THUMB bit */\n    *stack_size         = stack_len;\n\n    /*\n     * calculate the extra space we need to malloc\n     */\n    /* relocs are located in the .bss part of the BFLT binary, so we need whichever is biggest */\n    if ((relocs * sizeof(uint32_t)) > bss_len)\n        alloc_len = relocs * sizeof(uint32_t);\n    else\n        alloc_len = bss_len;\n    alloc_len += *data_len;\n\n\n    /*\n     * there are a couple of cases here:\n     *  -> the fully copied to RAM case which lumps it all together (RAM flag)\n     *  -> the separate code/data case (GOTPIC flag, w/o RAM flag)\n     */\n    if (flags & FLAT_FLAG_GZIP) {\n        kprintf(\"bFLT: GZIP compression not supported\\r\\n\");\n        goto error;\n    }\n\n    if (flags & FLAT_FLAG_GOTPIC) {\n        uint8_t  *mem, *copy_src;\n        uint32_t data_offset = 0;\n        uint32_t copy_len = *data_len;\n\n        if (flags & FLAT_FLAG_RAM) {\n            alloc_len += *text_len;\n            copy_len += *text_len;\n            data_offset = *text_len;\n        }\n\n        /* Allocate enough memory for .data, .bss and possibly .text */\n        mem = u_malloc(alloc_len);\n        if (!mem)\n        {\n            kprintf(\"bFLT: Could not allocate enough memory for process\\r\\n\");\n            goto error;\n        }\n\n        /* .text is only relocated when RAM flag is set */\n        if (flags & FLAT_FLAG_RAM) {\n            *reloc_text = mem;\n            copy_src = text_src;\n        } else {\n            *reloc_text = text_src;\n            copy_src = text_src + *text_len;\n        }\n        /* .data is always relocated */\n        data_dest = mem + data_offset;\n\n        *entry_point = *reloc_text + entry_point_offset;\n        *reloc_data = data_dest;\n        *reloc_bss = data_dest + *data_len;\n\n        /* copy segments .data segment and possibly .text */\n        memcpy(mem, copy_src, copy_len);\n        /* zero-init .bss */\n        memset(data_dest + *data_len, 0, bss_len);\n    } else {\n        /* GZIP or FULL RAM bFLTs not supported for now */\n        kprintf(\"bFLT: Only GOTPIC bFLT binaries are supported\\r\\n\");\n        goto error;\n    }\n\n\n    /*\n     * We just load the allocations into some temporary memory to\n     * help simplify all this mumbo jumbo\n     *\n     * We've got two different sections of relocation entries.\n     * The first is the GOT which resides at the beginning of the data segment\n     * and is terminated with a -1.  This one can be relocated in place.\n     * The second is the extra relocation entries tacked after the image's\n     * data segment. These require a little more processing as the entry is\n     * really an offset into the image which contains an offset into the\n     * image.\n     */\n\n    /* init relocations */\n    if (flags & FLAT_FLAG_GOTPIC) {\n        //printf(\"GOT-PIC!\\n\");\n        if (process_got_relocs(&hdr, address_zero, data_dest)) // .data section is beginning of GOT\n            goto error;\n        *got_loc = (uint32_t)data_dest;\n    }\n\n    /*\n     * Now run through the relocation entries.\n     */\n    process_relocs(&hdr, (uint32_t *)address_zero, (uint32_t)data_dest, (uint32_t *)relocs_src, relocs);\n\n    return 0;\n\nerror:\n    if (mem) kfree(mem);\n    *reloc_text  = NULL;\n    *reloc_data  = NULL;\n    *reloc_bss   = NULL;\n    *entry_point = NULL;\n    kprintf(\"bFLT: Caught error - exiting\\r\\n\");\n    return -1;\n}\n\n"
  },
  {
    "path": "kernel/bflt.h",
    "content": " /*\n */\n\n#include <frosted_api.h>\n#include \"flat.h\"\n\n#ifndef _BFLT_H_\n#define _BFLT_H_\n\nint bflt_load(uint8_t* from, void **reloc_text, void **reloc_data, void **reloc_bss,\n              void **entry_point, size_t *stack_size, uint32_t *got_loc, uint32_t *text_len, uint32_t *data_len);\n\n#endif\n"
  },
  {
    "path": "kernel/cdc_acm.h",
    "content": "#ifndef INC_CDC_ACM_H\n#define INC_CDC_ACM_H\n\n\nstruct cdcacm_addr {\n    const char * name;\n    const char * usb_name;\n};\n\nvoid cdcacm_init(struct fnode *dev, const struct cdcacm_addr cdcacm_addrs[], int num_cdcacm);\n\n\n#endif\n\n"
  },
  {
    "path": "kernel/cdc_ecm.h",
    "content": "#ifndef INC_CDC_ECM_H\n#define INC_CDC_ECM_H\n\n#define USBETH_MAX_FRAME 1514\n\n\n\nvoid cdcecm_init_init(const unsigned char * usb_name);\n\n\n#endif\n\n"
  },
  {
    "path": "kernel/cirbuf.c",
    "content": "/*  \n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as \n *      published by the Free Software Foundation.\n *      \n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */  \n\n#include \"frosted.h\"\n#include \"cirbuf.h\"\n#include \"errno.h\"\n\nstruct cirbuf {\n    uint8_t *buf;\n    uint8_t *readptr;\n    uint8_t *writeptr;\n    int     bufsize;\n};\n\nstruct cirbuf * cirbuf_create(int size)\n{\n    struct cirbuf* inbuf;\n    if (size <= 0) \n        return NULL;\n\n    inbuf = kalloc(sizeof(struct cirbuf));\n    if (!inbuf)\n        return NULL;\n\n    inbuf->buf = kalloc(size);\n    if (!inbuf->buf)\n    {\n        kfree(inbuf);\n        return NULL;\n    }\n\n    inbuf->bufsize = size;\n    inbuf->readptr = inbuf->buf;\n    inbuf->writeptr = inbuf->buf;\n    return inbuf;\n}\n\n/* 0 on success, -1 on fail */\nint cirbuf_writebyte(struct cirbuf *cb, uint8_t byte)\n{\n    if (!cb)\n        return -1;\n\n    /* check if there is space */\n    if (!cirbuf_bytesfree(cb))\n        return -1;\n\n    *cb->writeptr = byte;\n    cb->writeptr++;\n\n    /* wrap if needed */\n    if (cb->writeptr > (cb->buf + cb->bufsize - 1u))\n        cb->writeptr = cb->buf;\n\n    return 0;\n}\n\n/* 0 on success, -1 on fail */\nint cirbuf_readbyte(struct cirbuf *cb, uint8_t *byte)\n{\n    if (!cb || !byte)\n        return -1;\n\n    /* check if there is data */\n    if (!cirbuf_bytesinuse(cb))\n        return -1;\n\n    *byte = *cb->readptr++;\n\n    /* wrap if needed */\n    if (cb->readptr > (cb->buf + cb->bufsize - 1u))\n        cb->readptr = cb->buf;\n\n    return 0;\n}\n\nint cirbuf_readbytes(struct cirbuf *cb, void *bytes, int len)\n{\n    int buflen;\n    int i;\n    char *dst = bytes;\n    if (!cb || !bytes)\n        return -1;\n\n    /* check if there is data */\n    buflen = cirbuf_bytesinuse(cb);\n    if (buflen == 0)\n        return -1;\n    if (len > buflen)\n        len = buflen;\n\n    for (i = 0; i < len; i++) {\n        dst[i] = *(cb->readptr++);\n        /* wrap if needed */\n        if (cb->readptr > (cb->buf + cb->bufsize - 1u))\n            cb->readptr = cb->buf;\n    }\n    return len;\n}\n\n/* written len on success, 0 on fail */\nint cirbuf_writebytes(struct cirbuf *cb, const uint8_t * bytes, int len)\n{\n    uint8_t byte;\n    int freesize;\n    int tot_len = len;\n    if (!cb)\n        return 0;\n\n    /* check if there is space */\n    freesize = cirbuf_bytesfree(cb);\n    if (!freesize)\n        return 0;\n    if (freesize < len) {\n        len = freesize;\n        tot_len = freesize;\n    }\n\n    /* Wrap needed ? */\n    if ((cb->writeptr + len) > (cb->buf + cb->bufsize) - 1u)\n    {\n        int len_first_part = cb->buf + cb->bufsize - cb->writeptr; /* end - current position */\n        memcpy(cb->writeptr, bytes, len_first_part);\n        bytes += len_first_part;\n        cb->writeptr = cb->buf; /* set to start of buffer */\n        len -= len_first_part;\n    }\n    /* write remaining part */\n    if (len)\n    {\n        memcpy(cb->writeptr, bytes, len);\n        cb->writeptr += len;\n    }\n\n    return tot_len;\n}\n\nint cirbuf_bytesfree(struct cirbuf *cb)\n{\n    int bytes;\n    if (!cb)\n        return -1;\n\n    bytes = (int)(cb->readptr - cb->writeptr - 1);\n    if (cb->writeptr >= cb->readptr)\n        bytes += cb->bufsize;\n\n    return bytes;\n}\n\nint cirbuf_bytesinuse(struct cirbuf *cb)\n{\n    int bytes;\n    if (!cb)\n        return -1;\n\n    bytes = (int)(cb->writeptr - cb->readptr);\n    if (cb->writeptr < cb->readptr)\n        bytes += cb->bufsize;\n\n    return (bytes);\n}\n\n"
  },
  {
    "path": "kernel/cirbuf.h",
    "content": "#include \"frosted.h\"\n\n#ifndef CIR_BUF_H\n#define CIR_BUF_H\n\nstruct cirbuf;\n\nstruct cirbuf * cirbuf_create(int size);\n/* 0 on success, -1 on fail */\nint cirbuf_writebyte(struct cirbuf *cb, uint8_t byte);\n/* 0 on success, -1 on fail */\nint cirbuf_readbyte(struct cirbuf *cb, uint8_t *byte);\n/* len on success, -1 on fail */\nint cirbuf_writebytes(struct cirbuf *cb, const uint8_t * bytes, int len);\n\n/* len on success, -1 on fail */\nint cirbuf_readbytes(struct cirbuf *cb, void *bytes, int len);\nint cirbuf_bytesfree(struct cirbuf *cb);\nint cirbuf_bytesinuse(struct cirbuf *cb);\n\n#endif\n"
  },
  {
    "path": "kernel/crypto/aes.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Copyright (C) 2006-2016 wolfSSL Inc.\n *\n */\n\n#include \"frosted.h\"\n#include \"crypto/misc.h\"\n#include \"crypto/aes.h\"\n\n#define AES_MAX_KEY_SIZE    256\n#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y))))\n\nstatic const word32 rcon[] = {\n\t0x01000000, 0x02000000, 0x04000000, 0x08000000,\n\t0x10000000, 0x20000000, 0x40000000, 0x80000000,\n\t0x1B000000, 0x36000000,\n\t/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */\n};\n\nstatic const word32 Te[5][256] = {\n{\n\t0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,\n\t0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,\n\t0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,\n\t0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,\n\t0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,\n\t0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,\n\t0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,\n\t0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,\n\t0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,\n\t0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,\n\t0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,\n\t0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,\n\t0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,\n\t0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,\n\t0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,\n\t0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,\n\t0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,\n\t0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,\n\t0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,\n\t0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,\n\t0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,\n\t0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,\n\t0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,\n\t0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,\n\t0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,\n\t0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,\n\t0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,\n\t0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,\n\t0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,\n\t0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,\n\t0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,\n\t0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,\n\t0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,\n\t0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,\n\t0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,\n\t0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,\n\t0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,\n\t0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,\n\t0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,\n\t0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,\n\t0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,\n\t0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,\n\t0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,\n\t0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,\n\t0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,\n\t0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,\n\t0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,\n\t0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,\n\t0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,\n\t0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,\n\t0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,\n\t0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,\n\t0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,\n\t0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,\n\t0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,\n\t0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,\n\t0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,\n\t0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,\n\t0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,\n\t0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,\n\t0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,\n\t0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,\n\t0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,\n\t0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,\n},\n{\n\t0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,\n\t0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,\n\t0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,\n\t0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,\n\t0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,\n\t0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,\n\t0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,\n\t0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,\n\t0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,\n\t0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,\n\t0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,\n\t0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,\n\t0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,\n\t0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,\n\t0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,\n\t0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,\n\t0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,\n\t0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,\n\t0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,\n\t0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,\n\t0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,\n\t0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,\n\t0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,\n\t0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,\n\t0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,\n\t0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,\n\t0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,\n\t0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,\n\t0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,\n\t0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,\n\t0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,\n\t0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,\n\t0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,\n\t0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,\n\t0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,\n\t0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,\n\t0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,\n\t0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,\n\t0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,\n\t0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,\n\t0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,\n\t0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,\n\t0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,\n\t0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,\n\t0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,\n\t0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,\n\t0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,\n\t0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,\n\t0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,\n\t0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,\n\t0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,\n\t0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,\n\t0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,\n\t0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,\n\t0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,\n\t0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,\n\t0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,\n\t0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,\n\t0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,\n\t0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,\n\t0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,\n\t0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,\n\t0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,\n\t0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,\n},\n{\n\t0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,\n\t0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,\n\t0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,\n\t0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,\n\t0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,\n\t0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,\n\t0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,\n\t0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,\n\t0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,\n\t0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,\n\t0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,\n\t0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,\n\t0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,\n\t0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,\n\t0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,\n\t0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,\n\t0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,\n\t0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,\n\t0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,\n\t0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,\n\t0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,\n\t0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,\n\t0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,\n\t0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,\n\t0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,\n\t0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,\n\t0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,\n\t0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,\n\t0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,\n\t0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,\n\t0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,\n\t0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,\n\t0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,\n\t0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,\n\t0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,\n\t0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,\n\t0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,\n\t0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,\n\t0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,\n\t0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,\n\t0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,\n\t0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,\n\t0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,\n\t0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,\n\t0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,\n\t0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,\n\t0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,\n\t0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,\n\t0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,\n\t0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,\n\t0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,\n\t0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,\n\t0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,\n\t0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,\n\t0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,\n\t0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,\n\t0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,\n\t0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,\n\t0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,\n\t0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,\n\t0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,\n\t0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,\n\t0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,\n\t0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,\n},\n{\n\t0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,\n\t0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,\n\t0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,\n\t0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,\n\t0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,\n\t0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,\n\t0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,\n\t0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,\n\t0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,\n\t0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,\n\t0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,\n\t0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,\n\t0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,\n\t0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,\n\t0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,\n\t0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,\n\t0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,\n\t0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,\n\t0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,\n\t0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,\n\t0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,\n\t0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,\n\t0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,\n\t0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,\n\t0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,\n\t0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,\n\t0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,\n\t0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,\n\t0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,\n\t0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,\n\t0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,\n\t0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,\n\t0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,\n\t0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,\n\t0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,\n\t0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,\n\t0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,\n\t0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,\n\t0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,\n\t0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,\n\t0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,\n\t0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,\n\t0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,\n\t0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,\n\t0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,\n\t0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,\n\t0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,\n\t0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,\n\t0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,\n\t0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,\n\t0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,\n\t0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,\n\t0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,\n\t0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,\n\t0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,\n\t0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,\n\t0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,\n\t0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,\n\t0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,\n\t0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,\n\t0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,\n\t0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,\n\t0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,\n\t0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,\n},\n{\n\t0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,\n\t0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,\n\t0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,\n\t0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,\n\t0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,\n\t0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,\n\t0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,\n\t0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,\n\t0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,\n\t0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,\n\t0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,\n\t0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,\n\t0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,\n\t0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,\n\t0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,\n\t0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,\n\t0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,\n\t0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,\n\t0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,\n\t0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,\n\t0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,\n\t0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,\n\t0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,\n\t0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,\n\t0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,\n\t0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,\n\t0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,\n\t0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,\n\t0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,\n\t0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,\n\t0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,\n\t0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,\n\t0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,\n\t0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,\n\t0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,\n\t0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,\n\t0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,\n\t0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,\n\t0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,\n\t0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,\n\t0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,\n\t0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,\n\t0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,\n\t0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,\n\t0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,\n\t0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,\n\t0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,\n\t0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,\n\t0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,\n\t0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,\n\t0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,\n\t0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,\n\t0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,\n\t0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,\n\t0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,\n\t0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,\n\t0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,\n\t0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,\n\t0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,\n\t0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,\n\t0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,\n\t0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,\n\t0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,\n\t0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,\n}\n};\n\nstatic const word32 Td[5][256] = {\n{\n\t0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,\n\t0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,\n\t0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,\n\t0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,\n\t0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,\n\t0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,\n\t0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,\n\t0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,\n\t0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,\n\t0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,\n\t0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,\n\t0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,\n\t0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,\n\t0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,\n\t0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,\n\t0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,\n\t0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,\n\t0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,\n\t0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,\n\t0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,\n\t0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,\n\t0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,\n\t0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,\n\t0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,\n\t0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,\n\t0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,\n\t0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,\n\t0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,\n\t0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,\n\t0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,\n\t0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,\n\t0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,\n\t0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,\n\t0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,\n\t0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,\n\t0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,\n\t0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,\n\t0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,\n\t0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,\n\t0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,\n\t0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,\n\t0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,\n\t0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,\n\t0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,\n\t0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,\n\t0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,\n\t0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,\n\t0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,\n\t0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,\n\t0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,\n\t0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,\n\t0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,\n\t0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,\n\t0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,\n\t0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,\n\t0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,\n\t0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,\n\t0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,\n\t0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,\n\t0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,\n\t0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,\n\t0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,\n\t0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,\n\t0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,\n},\n{\n\t0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,\n\t0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,\n\t0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,\n\t0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,\n\t0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,\n\t0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,\n\t0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,\n\t0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,\n\t0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,\n\t0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,\n\t0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,\n\t0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,\n\t0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,\n\t0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,\n\t0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,\n\t0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,\n\t0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,\n\t0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,\n\t0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,\n\t0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,\n\t0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,\n\t0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,\n\t0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,\n\t0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,\n\t0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,\n\t0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,\n\t0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,\n\t0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,\n\t0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,\n\t0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,\n\t0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,\n\t0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,\n\t0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,\n\t0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,\n\t0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,\n\t0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,\n\t0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,\n\t0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,\n\t0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,\n\t0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,\n\t0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,\n\t0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,\n\t0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,\n\t0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,\n\t0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,\n\t0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,\n\t0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,\n\t0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,\n\t0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,\n\t0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,\n\t0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,\n\t0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,\n\t0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,\n\t0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,\n\t0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,\n\t0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,\n\t0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,\n\t0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,\n\t0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,\n\t0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,\n\t0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,\n\t0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,\n\t0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,\n\t0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,\n},\n{\n\t0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,\n\t0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,\n\t0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,\n\t0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,\n\t0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,\n\t0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,\n\t0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,\n\t0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,\n\t0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,\n\t0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,\n\t0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,\n\t0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,\n\t0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,\n\t0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,\n\t0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,\n\t0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,\n\t0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,\n\t0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,\n\t0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,\n\t0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,\n\n\t0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,\n\t0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,\n\t0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,\n\t0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,\n\t0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,\n\t0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,\n\t0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,\n\t0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,\n\t0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,\n\t0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,\n\t0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,\n\t0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,\n\t0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,\n\t0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,\n\t0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,\n\t0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,\n\t0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,\n\t0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,\n\t0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,\n\t0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,\n\t0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,\n\t0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,\n\t0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,\n\t0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,\n\t0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,\n\t0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,\n\t0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,\n\t0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,\n\t0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,\n\t0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,\n\t0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,\n\t0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,\n\t0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,\n\t0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,\n\t0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,\n\t0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,\n\t0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,\n\t0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,\n\t0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,\n\t0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,\n\t0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,\n\t0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,\n\t0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,\n\t0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,\n},\n{\n\t0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,\n\t0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,\n\t0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,\n\t0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,\n\t0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,\n\t0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,\n\t0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,\n\t0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,\n\t0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,\n\t0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,\n\t0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,\n\t0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,\n\t0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,\n\t0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,\n\t0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,\n\t0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,\n\t0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,\n\t0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,\n\t0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,\n\t0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,\n\t0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,\n\t0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,\n\t0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,\n\t0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,\n\t0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,\n\t0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,\n\t0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,\n\t0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,\n\t0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,\n\t0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,\n\t0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,\n\t0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,\n\t0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,\n\t0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,\n\t0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,\n\t0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,\n\t0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,\n\t0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,\n\t0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,\n\t0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,\n\t0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,\n\t0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,\n\t0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,\n\t0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,\n\t0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,\n\t0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,\n\t0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,\n\t0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,\n\t0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,\n\t0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,\n\t0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,\n\t0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,\n\t0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,\n\t0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,\n\t0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,\n\t0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,\n\t0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,\n\t0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,\n\t0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,\n\t0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,\n\t0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,\n\t0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,\n\t0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,\n\t0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,\n},\n{\n\t0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,\n\t0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,\n\t0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,\n\t0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,\n\t0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,\n\t0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,\n\t0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,\n\t0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,\n\t0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,\n\t0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,\n\t0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,\n\t0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,\n\t0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,\n\t0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,\n\t0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,\n\t0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,\n\t0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,\n\t0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,\n\t0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,\n\t0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,\n\t0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,\n\t0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,\n\t0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,\n\t0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,\n\t0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,\n\t0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,\n\t0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,\n\t0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,\n\t0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,\n\t0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,\n\t0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,\n\t0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,\n\t0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,\n\t0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,\n\t0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,\n\t0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,\n\t0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,\n\t0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,\n\t0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,\n\t0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,\n\t0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,\n\t0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,\n\t0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,\n\t0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,\n\t0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,\n\t0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,\n\t0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,\n\t0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,\n\t0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,\n\t0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,\n\t0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,\n\t0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,\n\t0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,\n\t0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,\n\t0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,\n\t0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,\n\t0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,\n\t0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,\n\t0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,\n\t0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,\n\t0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,\n\t0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,\n\t0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,\n\t0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,\n}\n};\n\nstatic int wc_AesSetIV(Aes *aes, const byte *iv)\n{\n\tif (aes == NULL)\n\t\treturn -1;\n\n\tif (iv)\n\t\tXMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);\n\telse\n\t\tXMEMSET(aes->reg,  0, AES_BLOCK_SIZE);\n\n\treturn 0;\n}\n\nstatic int wc_AesSetKeyLocal(Aes *aes, const byte *userKey, word32 keylen,\n\t\t\t\tconst byte *iv, int dir)\n{\n\tword32 temp, *rk = aes->key;\n\tunsigned int i = 0;\n\n\taes->rounds = keylen/4 + 6;\n\n\tXMEMCPY(rk, userKey, keylen);\n\tByteReverseWords(rk, rk, keylen);\n\n\tswitch(keylen) {\n\tcase 32:\n\t\twhile (1) {\n\t\t\ttemp = rk[ 7];\n\t\t\trk[ 8] = rk[ 0] ^\n\t\t\t\t(Te[4][GETBYTE(temp, 2)] & 0xff000000) ^\n\t\t\t\t(Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^\n\t\t\t\t(Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^\n\t\t\t\t(Te[4][GETBYTE(temp, 3)] & 0x000000ff) ^\n\t\t\t\trcon[i];\n\t\t\trk[ 9] = rk[ 1] ^ rk[ 8];\n\t\t\trk[10] = rk[ 2] ^ rk[ 9];\n\t\t\trk[11] = rk[ 3] ^ rk[10];\n\t\t\tif (++i == 7)\n\t\t\t\tbreak;\n\t\t\ttemp = rk[11];\n\t\t\trk[12] = rk[ 4] ^\n\t\t\t\t(Te[4][GETBYTE(temp, 3)] & 0xff000000) ^\n\t\t\t\t(Te[4][GETBYTE(temp, 2)] & 0x00ff0000) ^\n\t\t\t\t(Te[4][GETBYTE(temp, 1)] & 0x0000ff00) ^\n\t\t\t\t(Te[4][GETBYTE(temp, 0)] & 0x000000ff);\n\t\t\trk[13] = rk[ 5] ^ rk[12];\n\t\t\trk[14] = rk[ 6] ^ rk[13];\n\t\t\trk[15] = rk[ 7] ^ rk[14];\n\n\t\t\trk += 8;\n\t\t}\n\t\tbreak;\n\n\tdefault:\n\t\treturn -1;\n\t}\n\n\tif (dir == AES_DECRYPTION) {\n\t\tunsigned int j;\n\t\trk = aes->key;\n\n\t\t/* invert the order of the round keys: */\n\t\tfor (i = 0, j = 4* aes->rounds; i < j; i += 4, j -= 4) {\n\t\t\ttemp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;\n\t\t\ttemp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;\n\t\t\ttemp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;\n\t\t\ttemp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;\n\t\t}\n\t\t/* apply the inverse MixColumn transform to all round keys but the\n\t\t * first and the last:\n\t\t */\n\t\tfor (i = 1; i < aes->rounds; i++) {\n\t\t\trk += 4;\n\t\t\trk[0] =\n\t\t\t\tTd[0][Te[4][GETBYTE(rk[0], 3)] & 0xff] ^\n\t\t\t\tTd[1][Te[4][GETBYTE(rk[0], 2)] & 0xff] ^\n\t\t\t\tTd[2][Te[4][GETBYTE(rk[0], 1)] & 0xff] ^\n\t\t\t\tTd[3][Te[4][GETBYTE(rk[0], 0)] & 0xff];\n\t\t\trk[1] =\n\t\t\t\tTd[0][Te[4][GETBYTE(rk[1], 3)] & 0xff] ^\n\t\t\t\tTd[1][Te[4][GETBYTE(rk[1], 2)] & 0xff] ^\n\t\t\t\tTd[2][Te[4][GETBYTE(rk[1], 1)] & 0xff] ^\n\t\t\t\tTd[3][Te[4][GETBYTE(rk[1], 0)] & 0xff];\n\t\t\trk[2] =\n\t\t\t\tTd[0][Te[4][GETBYTE(rk[2], 3)] & 0xff] ^\n\t\t\t\tTd[1][Te[4][GETBYTE(rk[2], 2)] & 0xff] ^\n\t\t\t\tTd[2][Te[4][GETBYTE(rk[2], 1)] & 0xff] ^\n\t\t\t\tTd[3][Te[4][GETBYTE(rk[2], 0)] & 0xff];\n\t\t\trk[3] =\n\t\t\t\tTd[0][Te[4][GETBYTE(rk[3], 3)] & 0xff] ^\n\t\t\t\tTd[1][Te[4][GETBYTE(rk[3], 2)] & 0xff] ^\n\t\t\t\tTd[2][Te[4][GETBYTE(rk[3], 1)] & 0xff] ^\n\t\t\t\tTd[3][Te[4][GETBYTE(rk[3], 0)] & 0xff];\n\t\t}\n\t}\n\n\treturn wc_AesSetIV(aes, iv);\n}\n\nint wc_AesSetKey(Aes *aes, const byte *userKey, word32 keylen, const byte *iv,\n\t\t\tint dir)\n{\n\tconst word32 max_key_len = (AES_MAX_KEY_SIZE / 8);\n\n\tif (!(keylen == 32))\n\t\treturn -1;\n\n\tif (keylen > max_key_len) {\n\t\treturn -1;\n\t}\n\n\treturn wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir);\n}\n\nstatic void wc_AesEncrypt(Aes *aes, const byte *inBlock, byte *outBlock)\n{\n\tword32 s0, s1, s2, s3;\n\tword32 t0, t1, t2, t3;\n\tword32 r = aes->rounds >> 1;\n\n\tconst word32* rk = aes->key;\n\tif (r > 7 || r == 0) {\n\t\t//WOLFSSL_MSG(\"AesEncrypt encountered improper key, set it up\");\n\t\treturn;  /* stop instead of segfaulting, set up your keys! */\n\t}\n\n\t/*\n\t * map byte array block to cipher state\n\t * and add initial round key:\n\t */\n\tXMEMCPY(&s0, inBlock,                  sizeof(s0));\n\tXMEMCPY(&s1, inBlock + sizeof(s0),     sizeof(s1));\n\tXMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));\n\tXMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));\n\n\ts0 = ByteReverseWord32(s0);\n\ts1 = ByteReverseWord32(s1);\n\ts2 = ByteReverseWord32(s2);\n\ts3 = ByteReverseWord32(s3);\n\n\ts0 ^= rk[0];\n\ts1 ^= rk[1];\n\ts2 ^= rk[2];\n\ts3 ^= rk[3];\n\n\t/*\n\t * Nr - 1 full rounds:\n\t */\n\n\tfor (;;) {\n\t\tt0 =\n\t\t\tTe[0][GETBYTE(s0, 3)]  ^\n\t\t\tTe[1][GETBYTE(s1, 2)]  ^\n\t\t\tTe[2][GETBYTE(s2, 1)]  ^\n\t\t\tTe[3][GETBYTE(s3, 0)]  ^\n\t\t\trk[4];\n\t\tt1 =\n\t\t\tTe[0][GETBYTE(s1, 3)]  ^\n\t\t\tTe[1][GETBYTE(s2, 2)]  ^\n\t\t\tTe[2][GETBYTE(s3, 1)]  ^\n\t\t\tTe[3][GETBYTE(s0, 0)]  ^\n\t\t\trk[5];\n\t\tt2 =\n\t\t\tTe[0][GETBYTE(s2, 3)] ^\n\t\t\tTe[1][GETBYTE(s3, 2)]  ^\n\t\t\tTe[2][GETBYTE(s0, 1)]  ^\n\t\t\tTe[3][GETBYTE(s1, 0)]  ^\n\t\t\trk[6];\n\t\tt3 =\n\t\t\tTe[0][GETBYTE(s3, 3)] ^\n\t\t\tTe[1][GETBYTE(s0, 2)]  ^\n\t\t\tTe[2][GETBYTE(s1, 1)]  ^\n\t\t\tTe[3][GETBYTE(s2, 0)]  ^\n\t\t\trk[7];\n\n\t\trk += 8;\n\t\tif (--r == 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\ts0 =\n\t\t\tTe[0][GETBYTE(t0, 3)] ^\n\t\t\tTe[1][GETBYTE(t1, 2)] ^\n\t\t\tTe[2][GETBYTE(t2, 1)] ^\n\t\t\tTe[3][GETBYTE(t3, 0)] ^\n\t\t\trk[0];\n\t\ts1 =\n\t\t\tTe[0][GETBYTE(t1, 3)] ^\n\t\t\tTe[1][GETBYTE(t2, 2)] ^\n\t\t\tTe[2][GETBYTE(t3, 1)] ^\n\t\t\tTe[3][GETBYTE(t0, 0)] ^\n\t\t\trk[1];\n\t\ts2 =\n\t\t\tTe[0][GETBYTE(t2, 3)] ^\n\t\t\tTe[1][GETBYTE(t3, 2)] ^\n\t\t\tTe[2][GETBYTE(t0, 1)] ^\n\t\t\tTe[3][GETBYTE(t1, 0)] ^\n\t\t\trk[2];\n\t\ts3 =\n\t\t\tTe[0][GETBYTE(t3, 3)] ^\n\t\t\tTe[1][GETBYTE(t0, 2)] ^\n\t\t\tTe[2][GETBYTE(t1, 1)] ^\n\t\t\tTe[3][GETBYTE(t2, 0)] ^\n\t\t\trk[3];\n\t}\n\n\t/*\n\t * apply last round and\n\t * map cipher state to byte array block:\n\t */\n\n\ts0 =\n\t\t(Te[4][GETBYTE(t0, 3)] & 0xff000000) ^\n\t\t(Te[4][GETBYTE(t1, 2)] & 0x00ff0000) ^\n\t\t(Te[4][GETBYTE(t2, 1)] & 0x0000ff00) ^\n\t\t(Te[4][GETBYTE(t3, 0)] & 0x000000ff) ^\n\t\trk[0];\n\ts1 =\n\t\t(Te[4][GETBYTE(t1, 3)] & 0xff000000) ^\n\t\t(Te[4][GETBYTE(t2, 2)] & 0x00ff0000) ^\n\t\t(Te[4][GETBYTE(t3, 1)] & 0x0000ff00) ^\n\t\t(Te[4][GETBYTE(t0, 0)] & 0x000000ff) ^\n\t\trk[1];\n\ts2 =\n\t\t(Te[4][GETBYTE(t2, 3)] & 0xff000000) ^\n\t\t(Te[4][GETBYTE(t3, 2)] & 0x00ff0000) ^\n\t\t(Te[4][GETBYTE(t0, 1)] & 0x0000ff00) ^\n\t\t(Te[4][GETBYTE(t1, 0)] & 0x000000ff) ^\n\t\trk[2];\n\ts3 =\n\t\t(Te[4][GETBYTE(t3, 3)] & 0xff000000) ^\n\t\t(Te[4][GETBYTE(t0, 2)] & 0x00ff0000) ^\n\t\t(Te[4][GETBYTE(t1, 1)] & 0x0000ff00) ^\n\t\t(Te[4][GETBYTE(t2, 0)] & 0x000000ff) ^\n\t\trk[3];\n\n\t/* write out */\n\ts0 = ByteReverseWord32(s0);\n\ts1 = ByteReverseWord32(s1);\n\ts2 = ByteReverseWord32(s2);\n\ts3 = ByteReverseWord32(s3);\n\n\tXMEMCPY(outBlock,                  &s0, sizeof(s0));\n\tXMEMCPY(outBlock + sizeof(s0),     &s1, sizeof(s1));\n\tXMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));\n\tXMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));\n}\n\nstatic void wc_AesDecrypt(Aes *aes, const byte *inBlock, byte *outBlock)\n{\n\tword32 s0, s1, s2, s3;\n\tword32 t0, t1, t2, t3;\n\tword32 r = aes->rounds >> 1;\n\n\tconst word32 *rk = aes->key;\n\tif (r > 7 || r == 0) {\n\t\treturn;  /* stop instead of segfaulting, set up your keys! */\n\t}\n\n\t/*\n\t * map byte array block to cipher state\n\t * and add initial round key:\n\t */\n\tXMEMCPY(&s0, inBlock,                  sizeof(s0));\n\tXMEMCPY(&s1, inBlock + sizeof(s0),     sizeof(s1));\n\tXMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));\n\tXMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));\n\n\ts0 = ByteReverseWord32(s0);\n\ts1 = ByteReverseWord32(s1);\n\ts2 = ByteReverseWord32(s2);\n\ts3 = ByteReverseWord32(s3);\n\n\ts0 ^= rk[0];\n\ts1 ^= rk[1];\n\ts2 ^= rk[2];\n\ts3 ^= rk[3];\n\n\t/*\n\t * Nr - 1 full rounds:\n\t */\n\n\tfor (;;) {\n\t\tt0 =\n\t\t\tTd[0][GETBYTE(s0, 3)] ^\n\t\t\tTd[1][GETBYTE(s3, 2)] ^\n\t\t\tTd[2][GETBYTE(s2, 1)] ^\n\t\t\tTd[3][GETBYTE(s1, 0)] ^\n\t\t\trk[4];\n\t\tt1 =\n\t\t\tTd[0][GETBYTE(s1, 3)] ^\n\t\t\tTd[1][GETBYTE(s0, 2)] ^\n\t\t\tTd[2][GETBYTE(s3, 1)] ^\n\t\t\tTd[3][GETBYTE(s2, 0)] ^\n\t\t\trk[5];\n\t\tt2 =\n\t\t\tTd[0][GETBYTE(s2, 3)] ^\n\t\t\tTd[1][GETBYTE(s1, 2)] ^\n\t\t\tTd[2][GETBYTE(s0, 1)] ^\n\t\t\tTd[3][GETBYTE(s3, 0)] ^\n\t\t\trk[6];\n\t\tt3 =\n\t\t\tTd[0][GETBYTE(s3, 3)] ^\n\t\t\tTd[1][GETBYTE(s2, 2)] ^\n\t\t\tTd[2][GETBYTE(s1, 1)] ^\n\t\t\tTd[3][GETBYTE(s0, 0)] ^\n\t\t\trk[7];\n\n\t\trk += 8;\n\t\tif (--r == 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\ts0 =\n\t\t\tTd[0][GETBYTE(t0, 3)] ^\n\t\t\tTd[1][GETBYTE(t3, 2)] ^\n\t\t\tTd[2][GETBYTE(t2, 1)] ^\n\t\t\tTd[3][GETBYTE(t1, 0)] ^\n\t\t\trk[0];\n\t\ts1 =\n\t\t\tTd[0][GETBYTE(t1, 3)] ^\n\t\t\tTd[1][GETBYTE(t0, 2)] ^\n\t\t\tTd[2][GETBYTE(t3, 1)] ^\n\t\t\tTd[3][GETBYTE(t2, 0)] ^\n\t\t\trk[1];\n\t\ts2 =\n\t\t\tTd[0][GETBYTE(t2, 3)] ^\n\t\t\tTd[1][GETBYTE(t1, 2)] ^\n\t\t\tTd[2][GETBYTE(t0, 1)] ^\n\t\t\tTd[3][GETBYTE(t3, 0)] ^\n\t\t\trk[2];\n\t\ts3 =\n\t\t\tTd[0][GETBYTE(t3, 3)] ^\n\t\t\tTd[1][GETBYTE(t2, 2)] ^\n\t\t\tTd[2][GETBYTE(t1, 1)] ^\n\t\t\tTd[3][GETBYTE(t0, 0)] ^\n\t\t\trk[3];\n\t}\n\n\t/*\n\t * apply last round and\n\t * map cipher state to byte array block:\n\t */\n\ts0 =\n\t\t(Td[4][GETBYTE(t0, 3)] & 0xff000000) ^\n\t\t(Td[4][GETBYTE(t3, 2)] & 0x00ff0000) ^\n\t\t(Td[4][GETBYTE(t2, 1)] & 0x0000ff00) ^\n\t\t(Td[4][GETBYTE(t1, 0)] & 0x000000ff) ^\n\t\trk[0];\n\ts1 =\n\t\t(Td[4][GETBYTE(t1, 3)] & 0xff000000) ^\n\t\t(Td[4][GETBYTE(t0, 2)] & 0x00ff0000) ^\n\t\t(Td[4][GETBYTE(t3, 1)] & 0x0000ff00) ^\n\t\t(Td[4][GETBYTE(t2, 0)] & 0x000000ff) ^\n\t\trk[1];\n\ts2 =\n\t\t(Td[4][GETBYTE(t2, 3)] & 0xff000000) ^\n\t\t(Td[4][GETBYTE(t1, 2)] & 0x00ff0000) ^\n\t\t(Td[4][GETBYTE(t0, 1)] & 0x0000ff00) ^\n\t\t(Td[4][GETBYTE(t3, 0)] & 0x000000ff) ^\n\t\trk[2];\n\ts3 =\n\t\t(Td[4][GETBYTE(t3, 3)] & 0xff000000) ^\n\t\t(Td[4][GETBYTE(t2, 2)] & 0x00ff0000) ^\n\t\t(Td[4][GETBYTE(t1, 1)] & 0x0000ff00) ^\n\t\t(Td[4][GETBYTE(t0, 0)] & 0x000000ff) ^\n\t\trk[3];\n\n\t/* write out */\n\ts0 = ByteReverseWord32(s0);\n\ts1 = ByteReverseWord32(s1);\n\ts2 = ByteReverseWord32(s2);\n\ts3 = ByteReverseWord32(s3);\n\n\tXMEMCPY(outBlock,                  &s0, sizeof(s0));\n\tXMEMCPY(outBlock + sizeof(s0),     &s1, sizeof(s1));\n\tXMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));\n\tXMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));\n}\n\nint wc_AesCbcEncrypt(Aes *aes, byte *out, const byte *in, word32 sz)\n{\n\tword32 blocks = sz / AES_BLOCK_SIZE;\n\n\twhile (blocks--) {\n\t\txorbuf((byte *)aes->reg, in, AES_BLOCK_SIZE);\n\t\twc_AesEncrypt(aes, (byte*)aes->reg, (byte *)aes->reg);\n\t\tXMEMCPY(out, aes->reg, AES_BLOCK_SIZE);\n\n\t\tout += AES_BLOCK_SIZE;\n\t\tin  += AES_BLOCK_SIZE;\n\t}\n\n\treturn 0;\n}\n\nint wc_AesCbcDecrypt(Aes *aes, byte *out, const byte *in, word32 sz)\n{\n\tword32 blocks = sz / AES_BLOCK_SIZE;\n\n\twhile (blocks--) {\n\t\tXMEMCPY(aes->tmp, in, AES_BLOCK_SIZE);\n\t\twc_AesDecrypt(aes, (byte *)aes->tmp, out);\n\t\txorbuf(out, (byte *)aes->reg, AES_BLOCK_SIZE);\n\t\tXMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);\n\n\t\tout += AES_BLOCK_SIZE;\n\t\tin  += AES_BLOCK_SIZE;\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "kernel/crypto/aes.h",
    "content": "#ifndef CRYPTO_AES_H_\n#define CRYPTO_AES_H_\n\n#include \"crypto/misc.h\"\n\nenum {\n\tAES_ENC_TYPE   = 1,   /* cipher unique type */\n\tAES_ENCRYPTION = 0,\n\tAES_DECRYPTION = 1,\n\tAES_BLOCK_SIZE = 16\n};\n\ntypedef struct Aes {\n\t/* AESNI needs key first, rounds 2nd, not sure why yet */\n\t__attribute__ ( (aligned (16))) word32 key[60];\n\tword32  rounds;\n\n\t__attribute__ ( (aligned (16))) word32 reg[AES_BLOCK_SIZE / sizeof(word32)];      /* for CBC mode */\n\t__attribute__ ( (aligned (16))) word32 tmp[AES_BLOCK_SIZE / sizeof(word32)];      /* same         */\n\n\tvoid *heap; /* memory hint to use */\n} Aes;\n\n\nint wc_AesSetKey(Aes *aes, const byte *userKey, word32 keylen, const byte *iv,\n\t\t\tint dir);\nint wc_AesCbcEncrypt(Aes *aes, byte *out, const byte *in, word32 sz);\nint wc_AesCbcDecrypt(Aes *aes, byte *out, const byte *in, word32 sz);\n\n#endif /* CRYPTO_AES_H_ */\n"
  },
  {
    "path": "kernel/crypto/misc.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Copyright (C) 2006-2016 wolfSSL Inc.\n *\n */\n\n#include \"frosted.h\"\n#include \"crypto/misc.h\"\n\n\nword32 rotlFixed(word32 x, word32 y)\n{\n\treturn (x << y) | (x >> (sizeof(y) * 8 - y));\n}\n\nword32 rotrFixed(word32 x, word32 y)\n{\n\treturn (x >> y) | (x << (sizeof(y) * 8 - y));\n}\n\nword32 ByteReverseWord32(word32 value)\n{\n\t/* 6 instructions with rotate instruction, 8 without */\n\tvalue = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);\n\treturn rotlFixed(value, 16U);\n}\n\nvoid ByteReverseWords(word32 *out, const word32 *in, word32 byte_count)\n{\n\tword32 count = byte_count/(word32)sizeof(word32), i;\n\n\tfor (i = 0; i < count; i++)\n\t\tout[i] = ByteReverseWord32(in[i]);\n}\n\nstatic void XorWords(word32 *r, const word32 *a, word32 n)\n{\n\tword32 i;\n\n\tfor (i = 0; i < n; i++) r[i] ^= a[i];\n}\n\nvoid xorbuf(void *buf, const void *mask, word32 count)\n{\n\tif ((((word32)buf | (word32)mask | count) % sizeof(word32)) == 0)\n\t\tXorWords((word32 *)buf, (const word32 *)mask, (count / sizeof(word32)));\n\telse {\n\t\tword32 i;\n\t\tbyte *b = (byte *)buf;\n\t\tconst byte *m = (const byte *)mask;\n\n\t\tfor (i = 0; i < count; i++) b[i] ^= m[i];\n\t}\n}\n"
  },
  {
    "path": "kernel/crypto/misc.h",
    "content": "#ifndef CRYPTO_MISC_H_\n#define CRYPTO_MISC_H_\n\n#define XMEMCPY(d,s,l)    memcpy((d),(s),(l))\n#define XMEMSET(b,c,l)    memset((b),(c),(l))\n#define XMEMCMP(s1,s2,n)  memcmp((s1),(s2),(n))\n#define XMEMMOVE(d,s,l)   memmove((d),(s),(l))\n\n#ifndef byte\n    typedef unsigned char  byte;\n#endif\n\ntypedef unsigned short word16;\ntypedef unsigned int   word32;\n\nword32 rotlFixed(word32 x, word32 y);\nword32 rotrFixed(word32 x, word32 y);\nword32 ByteReverseWord32(word32 value);\nvoid ByteReverseWords(word32 *out, const word32 *in, word32 byte_count);\nvoid xorbuf(void *buf, const void *mask, word32 count);\n\n#endif /* CRYPTO_MISC_H_ */\n"
  },
  {
    "path": "kernel/crypto/sha256.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Copyright (C) 2006-2016 wolfSSL Inc.\n *  Code submitted to wolfSSL by raphael.huck@efixo.com\n *\n */\n\n#include \"frosted.h\"\n#include \"crypto/misc.h\"\n#include \"crypto/sha256.h\"\n\nstatic inline word32 min(word32 a, word32 b)\n{\n\treturn a > b ? b : a;\n}\n\nstatic const __attribute__ ((aligned (32))) word32 K[64] = {\n\t0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,\n\t0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,\n\t0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,\n\t0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,\n\t0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,\n\t0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,\n\t0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,\n\t0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,\n\t0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,\n\t0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,\n\t0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,\n\t0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,\n\t0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L\n};\n\n#define Ch(x,y,z)       ((z) ^ ((x) & ((y) ^ (z))))\n#define Maj(x,y,z)      ((((x) | (y)) & (z)) | ((x) & (y)))\n#define R(x, n)         (((x)&0xFFFFFFFFU)>>(n))\n\n#define S(x, n)         rotrFixed(x, n)\n#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))\n#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))\n#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))\n#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))\n\n#define RND(a,b,c,d,e,f,g,h,i) \\\n\t t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \\\n\t t1 = Sigma0((a)) + Maj((a), (b), (c)); \\\n\t (d) += t0; \\\n\t (h)  = t0 + t1;\n\nstatic int Transform(Sha256 *sha256)\n{\n\tword32 S[8], t0, t1;\n\tint i;\n\n\tword32 *W;\n\n\tW = (word32 *)kalloc(sizeof(word32) * 64);\n\tif (W == NULL)\n\t\treturn -1;\n\n\t/* Copy context->state[] to working vars */\n\tfor (i = 0; i < 8; i++)\n\t\tS[i] = sha256->digest[i];\n\n\tfor (i = 0; i < 16; i++)\n\t\tW[i] = sha256->buffer[i];\n\n\tfor (i = 16; i < 64; i++)\n\t\tW[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];\n\n\tfor (i = 0; i < 64; i += 8) {\n\t\tRND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);\n\t\tRND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);\n\t\tRND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);\n\t\tRND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);\n\t\tRND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);\n\t\tRND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);\n\t\tRND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);\n\t\tRND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);\n\t}\n\n\t/* Add the working vars back into digest state[] */\n\tfor (i = 0; i < 8; i++) {\n\t\tsha256->digest[i] += S[i];\n\t}\n\n\tkfree(W);\n\n\treturn 0;\n}\n\n#define XTRANSFORM(sha256, B) Transform(sha256)\n\nstatic inline void AddLength(Sha256 *sha256, word32 len)\n{\n\tword32 tmp = sha256->loLen;\n\tif ( (sha256->loLen += len) < tmp)\n\t\tsha256->hiLen++;                       /* carry low to high */\n}\n\nint wc_InitSha256(Sha256 *sha256)\n{\n\tint ret = 0;\n\tsha256->digest[0] = 0x6A09E667L;\n\tsha256->digest[1] = 0xBB67AE85L;\n\tsha256->digest[2] = 0x3C6EF372L;\n\tsha256->digest[3] = 0xA54FF53AL;\n\tsha256->digest[4] = 0x510E527FL;\n\tsha256->digest[5] = 0x9B05688CL;\n\tsha256->digest[6] = 0x1F83D9ABL;\n\tsha256->digest[7] = 0x5BE0CD19L;\n\n\tsha256->buffLen = 0;\n\tsha256->loLen   = 0;\n\tsha256->hiLen   = 0;\n\n\treturn ret;\n}\n\nint wc_Sha256Update(Sha256 *sha256, const byte *data, word32 len)\n{\n\t/* do block size increments */\n\tbyte *local = (byte *)sha256->buffer;\n\n\twhile (len) {\n\t\tword32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen);\n\t\tXMEMCPY(&local[sha256->buffLen], data, add);\n\n\t\tsha256->buffLen += add;\n\t\tdata            += add;\n\t\tlen             -= add;\n\n\t\tif (sha256->buffLen == SHA256_BLOCK_SIZE) {\n\t\t\tint ret;\n\n\t\t\tByteReverseWords(sha256->buffer, sha256->buffer,\n\t\t\t\t\t\t\t\t SHA256_BLOCK_SIZE);\n\t\t\tret = XTRANSFORM(sha256, local);\n\t\t\tif (ret != 0)\n\t\t\t\treturn ret;\n\n\t\t\tAddLength(sha256, SHA256_BLOCK_SIZE);\n\t\t\tsha256->buffLen = 0;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint wc_Sha256Final(Sha256 *sha256, byte *hash)\n{\n\tbyte *local = (byte *)sha256->buffer;\n\tint ret;\n\n\tAddLength(sha256, sha256->buffLen);  /* before adding pads */\n\n\tlocal[sha256->buffLen++] = 0x80;     /* add 1 */\n\n\t/* pad with zeros */\n\tif (sha256->buffLen > SHA256_PAD_SIZE) {\n\t\tXMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen);\n\t\tsha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen;\n\n\t\tByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE);\n\n\t\tret = XTRANSFORM(sha256, local);\n\t\tif (ret != 0)\n\t\t\treturn ret;\n\n\t\tsha256->buffLen = 0;\n\t}\n\tXMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen);\n\n\t/* put lengths in bits */\n\tsha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) +\n\t\t\t\t (sha256->hiLen << 3);\n\tsha256->loLen = sha256->loLen << 3;\n\n\t/* store lengths */\n\tByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE);\n\n\t/* ! length ordering dependent on digest endian type ! */\n\tXMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));\n\tXMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,\n\t\t\tsizeof(word32));\n\n\tret = XTRANSFORM(sha256, local);\n\tif (ret != 0)\n\t\treturn ret;\n\n\tByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE);\n\tXMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE);\n\n\treturn wc_InitSha256(sha256);  /* reset state */\n}\n"
  },
  {
    "path": "kernel/crypto/sha256.h",
    "content": "#ifndef CRYPTO_SHA256_H_\n#define CRYPTO_SHA256_H_\n\n#include \"crypto/misc.h\"\n\n/* in bytes */\nenum {\n\tSHA256             =  2,   /* hash type unique */\n\tSHA256_BLOCK_SIZE  = 64,\n\tSHA256_DIGEST_SIZE = 32,\n\tSHA256_PAD_SIZE    = 56\n};\n\n/* Sha256 digest */\ntypedef struct Sha256 {\n\tword32 buffLen;   /* in bytes          */\n\tword32 loLen;     /* length in bytes   */\n\tword32 hiLen;     /* length in bytes   */\n\tword32 digest[SHA256_DIGEST_SIZE / sizeof(word32)];\n\tword32 buffer[SHA256_BLOCK_SIZE  / sizeof(word32)];\n} Sha256;\n\nint wc_InitSha256(Sha256 *sha256);\nint wc_Sha256Update(Sha256 *sha256, const byte *data, word32 len);\nint wc_Sha256Final(Sha256 *sha256, byte *hash);\n\n#endif /* CRYPTO_SHA256_H_ */\n"
  },
  {
    "path": "kernel/device.h",
    "content": "#ifndef INC_DEVICE\n#define INC_DEVICE\n\n#include \"frosted.h\"\n\nstruct device {\n    struct fnode *fno;\n    mutex_t * mutex;\n    struct task *task;\n};\n\nint device_open(const char *path, int flags);\nstruct device *  device_fno_init(struct module * mod, const char * name, struct fnode *node, uint32_t flags,void * priv);\n\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/device.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n\nint device_open(const char *path, int flags)\n{\n    struct fnode *f = fno_search(path);\n    if (!f)\n        return -1;\n    return task_filedesc_add(f);\n}\n\nstruct device *  device_fno_init(struct module * mod, const char * name, struct fnode *node, uint32_t flags, void * priv)\n{\n    struct device * device = kalloc(sizeof(struct device));\n    device->fno = NULL;\n    /* Only create a device node if there is a name */\n    if(name)\n    {\n        device->fno =  fno_create(mod, name, node);\n        device->fno->priv = priv;\n        device->fno->flags |= flags;\n    }\n    device->task = NULL;\n    device->mutex = mutex_init();\n    return device;\n}\n"
  },
  {
    "path": "kernel/drivers/devusb_cdc_ecm.c",
    "content": "/*\n *\tUSB Ethernet gadget driver\n *\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include <pico_stack.h>\n#include <pico_device.h>\n#include <pico_ipv4.h>\n#include \"usb.h\"\n\n#define USBETH_MAX_FRAME 1514\n\nstruct pico_dev_usbeth {\n    struct pico_device dev;\n};\n\nstruct usbeth_rx_buffer {\n    enum usbeth_rx_buffer_status {\n        RX_STATUS_FREE, /**< Buffer is free */\n        RX_STATUS_INCOMING, /**< We have unprocessed buffer */\n        RX_STATUS_TCPIP /** PICO TCP is processing */\n    } status;\n\n    uint16_t size;\n    uint8_t buf[USBETH_MAX_FRAME];\n};\n\nstruct usbeth_tx_buffer {\n    enum usbeth_tx_buffer_status {\n        TX_STATUS_FREE,\n        TX_STATUS_PENDING,\n        TX_STATUS_COMPLETE\n    } status;\n\n    uint16_t size;\n    uint8_t buf[USBETH_MAX_FRAME];\n};\n\nstatic struct pico_dev_usbeth *pico_usbeth = NULL;\nstatic struct usbeth_rx_buffer *rx_buffer = NULL;\nstatic struct usbeth_tx_buffer *tx_buffer = NULL;\n\nstatic const struct __attribute__((packed)) {\n    struct usb_config_descriptor config;\n\n    struct usb_interface_descriptor comm_iface;\n    struct {\n        struct usb_cdc_header_descriptor header;\n        struct usb_cdc_union_descriptor cdc_union;\n        struct usb_cdc_ecm_descriptor ecm;\n    } __attribute__((packed)) functional_descriptors;\n    struct usb_endpoint_descriptor comm_endp;\n\n    struct usb_interface_descriptor data_iface;\n    struct usb_endpoint_descriptor data_endp[2];\n} cdc_ecm_config = {\n    .config = {\n        .bLength = USB_DT_CONFIGURATION_SIZE,\n        .bDescriptorType = USB_DT_CONFIGURATION,\n        .wTotalLength = sizeof(cdc_ecm_config),\n        .bNumInterfaces = 2,\n        .bConfigurationValue = 1,\n        .iConfiguration = 0,\n        .bmAttributes = 0xC0,\n        .bMaxPower = 0x32\n    },\n\n    .comm_iface = {\n        .bLength = USB_DT_INTERFACE_SIZE,\n        .bDescriptorType = USB_DT_INTERFACE,\n        .bInterfaceNumber = 0,\n        .bAlternateSetting = 0,\n        .bNumEndpoints = 1,\n        .bInterfaceClass = USB_CLASS_CDC,\n        .bInterfaceSubClass = USB_CDC_SUBCLASS_ECM,\n        .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE,\n        .iInterface = 0\n    },\n\n    .functional_descriptors = {\n        .header = {\n            .bFunctionLength = sizeof(struct usb_cdc_header_descriptor),\n            .bDescriptorType = CS_INTERFACE,\n            .bDescriptorSubtype = USB_CDC_TYPE_HEADER,\n            .bcdCDC = 0x0120,\n        },\n        .cdc_union = {\n            .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),\n            .bDescriptorType = CS_INTERFACE,\n            .bDescriptorSubtype = USB_CDC_TYPE_UNION,\n            .bControlInterface = 0,\n            .bSubordinateInterface0 = 1,\n         },\n        .ecm = {\n            .bFunctionLength = sizeof(struct usb_cdc_ecm_descriptor),\n            .bDescriptorType = CS_INTERFACE,\n            .bDescriptorSubtype = USB_CDC_TYPE_ECM,\n            .iMACAddress = 4,\n            .bmEthernetStatistics = { 0, 0, 0, 0 },\n            .wMaxSegmentSize = USBETH_MAX_FRAME,\n            .wNumberMCFilters = 0,\n            .bNumberPowerFilters = 0,\n        },\n    },\n\n    .comm_endp = {\n        .bLength = USB_DT_ENDPOINT_SIZE,\n        .bDescriptorType = USB_DT_ENDPOINT,\n        .bEndpointAddress = 0x82,\n        .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,\n        .wMaxPacketSize = 16,\n        .bInterval = 0x10,\n    },\n\n    .data_iface = {\n        .bLength = USB_DT_INTERFACE_SIZE,\n        .bDescriptorType = USB_DT_INTERFACE,\n        .bInterfaceNumber = 1,\n        .bAlternateSetting = 0,\n        .bNumEndpoints = 2,\n        .bInterfaceClass = USB_CLASS_DATA,\n        .bInterfaceSubClass = 0,\n        .bInterfaceProtocol = 0,\n        .iInterface = 0\n    },\n\n\n    .data_endp = {{\n        .bLength = USB_DT_ENDPOINT_SIZE,\n        .bDescriptorType = USB_DT_ENDPOINT,\n        .bEndpointAddress = 0x01,\n        .bmAttributes = USB_ENDPOINT_ATTR_BULK,\n        .wMaxPacketSize = 64,\n        .bInterval = 1,\n    }, {\n        .bLength = USB_DT_ENDPOINT_SIZE,\n        .bDescriptorType = USB_DT_ENDPOINT,\n        .bEndpointAddress = 0x81,\n        .bmAttributes = USB_ENDPOINT_ATTR_BULK,\n        .wMaxPacketSize = 64,\n        .bInterval = 1,\n    }}\n};\n\nstatic const struct usb_string_descriptor string_lang_list = {\n    .bLength = USB_DT_STRING_SIZE(1),\n    .bDescriptorType = USB_DT_STRING,\n    .wData = {\n        USB_LANGID_ENGLISH_UNITED_STATES\n    }\n};\n\nconst struct usb_string_descriptor usb_string_manuf = {\n    .bLength = USB_DT_STRING_SIZE(22),\n    .bDescriptorType = USB_DT_STRING,\n    /* Insane adding machines */\n    .wData = {\n        0x0049, 0x006e, 0x0073, 0x0061, 0x006e, 0x0065, 0x0020, 0x0061,\n        0x0064, 0x0064, 0x0069, 0x006e, 0x0067, 0x0020, 0x006d, 0x0061,\n        0x0063, 0x0068, 0x0069, 0x006e, 0x0065, 0x0073\n    }\n};\n\nstatic const struct usb_string_descriptor usb_string_name = {\n    .bLength = USB_DT_STRING_SIZE(18),\n    .bDescriptorType = USB_DT_STRING,\n    /* Frosted Eth gadget */\n    .wData = {\n        0x0046, 0x0072, 0x006f, 0x0073, 0x0074, 0x0065, 0x0064, 0x0020,\n        0x0045, 0x0074, 0x0068, 0x0020, 0x0067, 0x0061, 0x0064, 0x0067,\n        0x0065, 0x0074\n    }\n};\n\nstatic const struct usb_string_descriptor usb_serialn = {\n    .bLength = USB_DT_STRING_SIZE(2),\n    .bDescriptorType = USB_DT_STRING,\n    /* 01 */\n    .wData = {\n        0x0030, 0x0031\n    }\n};\n\nstatic const struct usb_string_descriptor usb_macaddr = {\n    .bLength = USB_DT_STRING_SIZE(12),\n    .bDescriptorType = USB_DT_STRING,\n    /* 005af341b4c9 */\n    .wData = {\n        0x0030, 0x0030, 0x0035, 0x0061, 0x0066, 0x0033, 0x0034, 0x0031,\n        0x0062, 0x0034, 0x0063, 0x0039\n    }\n};\n\nstatic const struct usb_string_descriptor **string_data[1] = {\n    (const struct usb_string_descriptor *[]) {\n        &usb_string_manuf,\n        &usb_string_name,\n        &usb_serialn,\n        &usb_macaddr\n    }\n};\n\nstatic const struct usbd_info_string string = {\n    .lang_list = &string_lang_list,\n    .count = 4,\n    .data = string_data\n};\n\nstatic const struct usb_device_descriptor cdc_ecm_dev = {\n    .bLength = USB_DT_DEVICE_SIZE,\n    .bDescriptorType = USB_DT_DEVICE,\n    .bcdUSB = 0x0200,\n    .bDeviceClass = USB_CLASS_CDC,\n    .bDeviceSubClass = 0,\n    .bDeviceProtocol = 0,\n    .bMaxPacketSize0 = 64,\n    .idVendor = 0x0483,\n    .idProduct = 0x5740,\n    .bcdDevice = 0x0200,\n    .iManufacturer = 1,\n    .iProduct = 2,\n    .iSerialNumber = 3,\n    .bNumConfigurations = 1\n};\n\nstatic const struct usbd_info cdc_ecm_info = {\n    .device = {\n        .desc = &cdc_ecm_dev,\n        .string = &string\n    },\n\n    .config = {{\n        .desc = (const struct usb_config_descriptor *) &cdc_ecm_config,\n        .string = &string\n    }}\n};\n\nstatic const uint8_t mac_addr[6] = { 0, 0x5a, 0xf3, 0x41, 0xb4, 0xca };\n\nstatic void cdcecm_setup_request(usbd_device *usbd_dev, uint8_t ep_addr,\n            const struct usb_setup_data *setup_data)\n{\n    (void) ep_addr; /* Assuming (ep_addr == 0) */\n\n    const uint8_t bmReqMask = USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT;\n    const uint8_t bmReqVal = USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE;\n\n    if ((setup_data->bmRequestType & bmReqMask) != bmReqVal) {\n        /* Not of our interest, let library handle */\n        usbd_ep0_setup(usbd_dev, setup_data);\n        return;\n    }\n\n    switch (setup_data->bRequest) {\n    case USB_CDC_REQ_SET_ETHERNET_MULTICAST_FILTER:\n    case USB_CDC_REQ_SET_ETHERNET_PACKET_FILTER:\n    case USB_CDC_REQ_SET_ETHERNET_PM_PATTERN_FILTER:\n    case USB_CDC_REQ_SET_CONTROL_LINE_STATE:\n        usbd_ep0_transfer(usbd_dev, setup_data, NULL, 0, NULL);\n        return;\n    case USB_CDC_REQ_SET_LINE_CODING: {\n        if (setup_data->wLength < sizeof(struct usb_cdc_line_coding)) {\n            break;\n        }\n\n        /* Just read whatever the host is sending */\n        uint8_t buf[sizeof(struct usb_cdc_line_coding)];\n        usbd_ep0_transfer(usbd_dev, setup_data, buf,\n                setup_data->wLength, NULL);\n    } return;\n    }\n\n    /* Unsupported request */\n    usbd_ep0_stall(usbd_dev);\n}\n\n\n\n\n/***************************\n *                         *\n *  USB Device Definition  *\n *                         *\n ***************************\n *\n *\n */\nstatic void cdcecm_set_config(usbd_device *usbd_dev,\n        const struct usb_config_descriptor *cfg);\n\nstatic usbd_device *usbd_dev;\n\nstatic void notify_link_up(void)\n{\n    static const uint8_t buf[8] = {0x51, 0, 1, 0, 0, 0, 0, 0};\n    const usbd_transfer transfer = {\n        .ep_type = USBD_EP_INTERRUPT,\n        .ep_addr = 0x82,\n        .ep_size = 16,\n        .ep_interval = 0,\n        .buffer = (void *) buf,\n        .length = sizeof(buf),\n        .flags = USBD_FLAG_NONE,\n        .timeout = USBD_TIMEOUT_NEVER,\n        .callback = NULL\n    };\n\n    usbd_transfer_submit(usbd_dev, &transfer);\n}\n\nstatic void bulk_out_callback(usbd_device *dev,\n            const usbd_transfer *transfer, usbd_transfer_status status,\n            usbd_urb_id urb_id)\n{\n    static int notified_link_up = 0;\n    static int fail_count = 0;\n    (void)urb_id;\n\n    if (status != USBD_SUCCESS) {\n        return;\n    }\n\n    if (!notified_link_up) {\n        notified_link_up = 1;\n        notify_link_up();\n    }\n\n    if (rx_buffer->status == RX_STATUS_FREE) {\n        rx_buffer->size = transfer->transferred;\n        rx_buffer->status = RX_STATUS_INCOMING;\n    } else {\n        if(++fail_count > 100) {\n            rx_buffer->status = RX_STATUS_FREE;\n        }\n    }\n    frosted_tcpip_wakeup();\n}\n\nstatic void bulk_out_submit(void)\n{\n    rx_buffer->size = 0;\n    rx_buffer->status = RX_STATUS_FREE;\n\n    const usbd_transfer transfer = {\n        .ep_type = USBD_EP_BULK,\n        .ep_addr = 0x01,\n        .ep_size = 64,\n        .ep_interval = USBD_INTERVAL_NA,\n        .buffer = rx_buffer->buf,\n        .length = USBETH_MAX_FRAME,\n        .flags = USBD_FLAG_SHORT_PACKET,\n        .timeout = USBD_TIMEOUT_NEVER,\n        .callback = bulk_out_callback\n    };\n\n    usbd_transfer_submit(usbd_dev, &transfer);\n}\n\nstatic void cdcecm_set_config(usbd_device *usbd_dev,\n        const struct usb_config_descriptor *cfg)\n{\n    (void)cfg;\n\n    usbd_ep_prepare(usbd_dev, 0x01, USBD_EP_BULK, 64, USBD_INTERVAL_NA, USBD_EP_NONE);\n    usbd_ep_prepare(usbd_dev, 0x81, USBD_EP_BULK, 64, USBD_INTERVAL_NA, USBD_EP_NONE);\n    usbd_ep_prepare(usbd_dev, 0x82, USBD_EP_INTERRUPT, 16, 0, USBD_EP_NONE);\n\n    bulk_out_submit();\n}\n\n/**\n * Transfer callback for BULK IN (TX)\n */\nstatic void bulk_in_callback(usbd_device *dev,\n    const usbd_transfer *transfer, usbd_transfer_status status,\n    usbd_urb_id urb_id)\n{\n    (void)dev;\n    (void)transfer;\n    (void)urb_id;\n\n    tx_buffer->status = TX_STATUS_COMPLETE;\n    frosted_tcpip_wakeup();\n}\n\nstatic int pico_usbeth_send(struct pico_device *dev, void *buf, int len)\n{\n    struct pico_dev_usbeth *usbeth = (struct pico_dev_usbeth *) dev;\n    static int fail_count = 0;\n    const usbd_transfer transfer = {\n        .ep_type = USBD_EP_BULK,\n        .ep_addr = 0x81,\n        .ep_size = 64,\n        .ep_interval = USBD_INTERVAL_NA,\n        .buffer = tx_buffer->buf,\n        .length = len,\n        .flags = USBD_FLAG_NONE,\n        .timeout = USBD_TIMEOUT_NEVER,\n        .callback = bulk_in_callback\n    };\n\n    if (tx_buffer->status == TX_STATUS_PENDING) {\n        if (++fail_count > 100)\n            tx_buffer->status == TX_STATUS_FREE;\n        return 0;\n    }\n    tx_buffer->status = TX_STATUS_PENDING;\n    if (len > USBETH_MAX_FRAME)\n        len = USBETH_MAX_FRAME;\n    memcpy(tx_buffer->buf, buf, len);\n    tx_buffer->size = len;\n    usbd_transfer_submit(usbd_dev, &transfer);\n    return len;\n}\n\nstatic int pico_usbeth_poll(struct pico_device *dev, int loop_score)\n{\n    if (rx_buffer->status == RX_STATUS_INCOMING) {\n        pico_stack_recv(&pico_usbeth->dev, rx_buffer->buf, rx_buffer->size);\n        bulk_out_submit();\n        loop_score--;\n    }\n    return loop_score;\n}\n\nstatic void pico_usbeth_destroy(struct pico_device *dev)\n{\n    struct pico_dev_usbeth *usbeth = (struct pico_dev_usbeth *) dev;\n    kfree(rx_buffer);\n    kfree(tx_buffer);\n    kfree(usbeth);\n    usbeth = NULL;\n    rx_buffer = NULL;\n    tx_buffer = NULL;\n}\n\nint usb_ethernet_init(unsigned int dev)\n{\n    struct pico_dev_usbeth *usb = kalloc(sizeof(*usb));\n    uint8_t *usb_buf;\n    struct pico_ip4 default_ip, default_nm, default_gw, zero;\n    const char ipstr[] = CONFIG_USB_DEFAULT_IP;\n    const char nmstr[] = CONFIG_USB_DEFAULT_NM;\n    const char gwstr[] = CONFIG_USB_DEFAULT_GW;\n    zero.addr = 0U;\n\n    if (!rx_buffer) {\n        rx_buffer = kalloc(sizeof(*rx_buffer));\n        if (!rx_buffer)\n            return -1;\n    }\n    if (!tx_buffer) {\n        tx_buffer = kalloc(sizeof(*tx_buffer));\n        if (!tx_buffer) {\n            kfree(rx_buffer);\n            return -1;\n        }\n    }\n\n    pico_string_to_ipv4(ipstr, &default_ip.addr);\n    pico_string_to_ipv4(nmstr, &default_nm.addr);\n    pico_string_to_ipv4(gwstr, &default_gw.addr);\n    memset(usb, 0, sizeof(struct pico_dev_usbeth));\n\n    usb->dev.overhead = 0;\n    usb->dev.send = pico_usbeth_send;\n    usb->dev.poll = pico_usbeth_poll;\n    usb->dev.destroy = pico_usbeth_destroy;\n    if (pico_device_init(&usb->dev,\"usb0\", mac_addr) < 0) {\n        kfree(usb_buf);\n        kfree(usb);\n        return -1;\n    }\n\n    pico_usbeth = usb;\n    /* Set address/netmask */\n    pico_ipv4_link_add(&usb->dev, default_ip, default_nm);\n    /* Set default gateway */\n    pico_ipv4_route_add(zero, zero, default_gw, 1, NULL);\n    tx_buffer->status = TX_STATUS_FREE;\n    if (usbdev_start(&usbd_dev, dev, &cdc_ecm_info) < 0) {\n        return -EBUSY;\n    }\n\n    usbd_register_set_config_callback(usbd_dev, cdcecm_set_config);\n    usbd_register_setup_callback(usbd_dev, cdcecm_setup_request);\n\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/dma.h",
    "content": "#ifndef INC_DMA\n#define INC_DMA\n\nstruct dma_config {\n    uint32_t base;\n    uint8_t stream;\n    uint32_t channel;\n    uint32_t psize;\n    uint32_t msize;\n    uint32_t dirn;\n    uint32_t prio;\n    uint32_t paddr;\n    uint32_t irq;\n};\n\nvoid init_dma(const struct dma_config * dma, uint32_t ptr, uint32_t len);\n\n#endif\n\n"
  },
  {
    "path": "kernel/drivers/dsp.h",
    "content": "#ifndef INC_DSP\n#define INC_DSP\n\n#ifdef CONFIG_DSP\nint dsp_init(void);\n#else\n#  define dsp_init() ((-ENOENT))\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/eth.h",
    "content": "#ifndef INC_ETH\n#define INC_ETH\n#include \"frosted.h\"\n#include \"gpio.h\"\n\nstruct eth_config {\n    const struct gpio_config *pio_mii;\n    const unsigned int n_pio_mii;\n    const struct gpio_config pio_phy_reset;\n    const int has_phy_reset;\n};\n\n#ifdef CONFIG_DEVETH\nint ethernet_init(const struct eth_config *conf);\nint pico_eth_start(void);\n#else\n#  define ethernet_init(x) ((-ENOENT))\n#  define pico_eth_start() ((-ENOENT))\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/exti.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: danielinux, DarkVegetableMatter\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"ioctl.h\"\n\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/exti.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/cm3/nvic.h>\n\n#include \"gpio.h\"\n#include \"exti.h\"\n\nstruct dev_exti {\n    int exti;                               /* Exti index in the dev_exti[] array */\n    uint32_t base;                          /* GPIO base */\n    uint16_t pin;                           /* GPIO pin */\n    uint8_t trigger;                        /* EXTI trigger type */\n    void (* exti_isr)(void *);                /* ISR */\n    void *exti_isr_arg;\n};\n\n#define MAX_EXTIS   24\n\nstatic struct dev_exti *DEV_EXTI[MAX_EXTIS];\n\nvoid exti_isr(uint32_t exti_base, uint32_t exti_idx)\n{\n    struct dev_exti *dev = DEV_EXTI[exti_idx];\n    exti_reset_request(exti_base);\n    if (dev && dev->exti_isr) {\n        dev->exti_isr(dev->exti_isr_arg);\n    }\n}\n\nvoid exti0_isr(void)\n{\n    exti_isr(EXTI0, 0);\n}\n\nvoid exti1_isr(void)\n{\n    exti_isr(EXTI1, 1);\n}\n\nvoid exti2_isr(void)\n{\n    exti_isr(EXTI2, 2);\n}\n\nvoid exti3_isr(void)\n{\n    exti_isr(EXTI3, 3);\n}\n\nvoid exti4_isr(void)\n{\n    exti_isr(EXTI4, 4);\n}\n\nvoid exti9_5_isr(void)\n{\n    if(exti_get_flag_status(EXTI5))\n        exti_isr(EXTI5, 5);\n    if(exti_get_flag_status(EXTI6))\n        exti_isr(EXTI6, 6);\n    if(exti_get_flag_status(EXTI7))\n        exti_isr(EXTI7, 7);\n    if(exti_get_flag_status(EXTI8))\n        exti_isr(EXTI8, 8);\n    if(exti_get_flag_status(EXTI9))\n        exti_isr(EXTI9, 9);\n}\n\nvoid exti15_10_isr(void)\n{\n    if(exti_get_flag_status(EXTI10))\n        exti_isr(EXTI10, 10);\n    if(exti_get_flag_status(EXTI11))\n        exti_isr(EXTI11, 11);\n    if(exti_get_flag_status(EXTI12))\n        exti_isr(EXTI12, 12);\n    if(exti_get_flag_status(EXTI13))\n        exti_isr(EXTI13, 13);\n    if(exti_get_flag_status(EXTI14))\n        exti_isr(EXTI14, 14);\n    if(exti_get_flag_status(EXTI15))\n        exti_isr(EXTI15, 15);\n}\n\nstatic uint32_t exti_base(uint16_t pin)\n{\n    switch(pin)\n    {\n        case GPIO0:\n            return EXTI0;\n        case GPIO1:\n            return EXTI1;\n        case GPIO2:\n            return EXTI2;\n        case GPIO3:\n            return EXTI3;\n        case GPIO4:\n            return EXTI4;\n        case GPIO5:\n            return EXTI5;\n        case GPIO6:\n            return EXTI6;\n        case GPIO7:\n            return EXTI7;\n        case GPIO8:\n            return EXTI8;\n        case GPIO9:\n            return EXTI9;\n        case GPIO10:\n            return EXTI10;\n        case GPIO11:\n            return EXTI11;\n        case GPIO12:\n            return EXTI12;\n        case GPIO13:\n            return EXTI13;\n        case GPIO14:\n            return EXTI14;\n        case GPIO15:\n            return EXTI15;\n    }\n    return (uint32_t)(-1);\n}\n\n\nstatic int gpio_id(uint16_t pin)\n{\n    switch(pin)\n    {\n        case GPIO0:\n            return 0;\n        case GPIO1:\n            return 1;\n        case GPIO2:\n            return 2;\n        case GPIO3:\n            return 3;\n        case GPIO4:\n            return 4;\n        case GPIO5:\n            return 5;\n        case GPIO6:\n            return 6;\n        case GPIO7:\n            return 7;\n        case GPIO8:\n            return 8;\n        case GPIO9:\n            return 9;\n        case GPIO10:\n            return 10;\n        case GPIO11:\n            return 11;\n        case GPIO12:\n            return 12;\n        case GPIO13:\n            return 13;\n        case GPIO14:\n            return 14;\n        case GPIO15:\n            return 15;\n    }\n    return -1;\n}\n\nint exti_register(uint32_t base, uint16_t pin, uint8_t trigger, void (*isr)(void *), void *isr_arg)\n{\n\n    uint32_t exti = exti_base(pin);\n    struct dev_exti *e;\n    int idx = gpio_id(pin);\n\n    if (idx < 0)\n        return -EINVAL;\n\n    if (DEV_EXTI[idx] != NULL)\n        return -EEXIST;\n\n    e = kalloc(sizeof(struct dev_exti));\n    if (!e)\n        return -ENOMEM;\n\n    e->base = base;\n    e->pin = pin;\n    e->trigger = trigger;\n    e->exti_isr = isr;\n    e->exti_isr_arg = isr_arg;\n    exti_select_source(exti, base);\n    exti_set_trigger(exti, trigger);\n    DEV_EXTI[idx] = e;\n    return idx;\n}\n\nvoid exti_unregister(int idx)\n{\n    if(DEV_EXTI[idx]) {\n        kfree(DEV_EXTI[idx]);\n        DEV_EXTI[idx] = NULL;\n    }\n}\n\nint exti_enable(int idx, int enable)\n{\n    if (DEV_EXTI[idx]) {\n        if(enable)\n            exti_enable_request(exti_base(idx));\n        else\n            exti_disable_request(exti_base(idx));\n        return 0;\n    }\n}\n\n\nvoid exti_init(void)\n{\n    int i;\n    uint32_t exti_irq;\n    rcc_periph_clock_enable(RCC_SYSCFG);\n\n    for(i=0; i < MAX_EXTIS; i++)\n    {\n        DEV_EXTI[i] = NULL;\n    }\n    nvic_enable_irq(NVIC_EXTI0_IRQ);\n    nvic_enable_irq(NVIC_EXTI1_IRQ);\n    nvic_enable_irq(NVIC_EXTI2_IRQ);\n    nvic_enable_irq(NVIC_EXTI3_IRQ);\n    nvic_enable_irq(NVIC_EXTI4_IRQ);\n    nvic_enable_irq(NVIC_EXTI9_5_IRQ);\n    nvic_enable_irq(NVIC_EXTI15_10_IRQ);\n}\n"
  },
  {
    "path": "kernel/drivers/exti.h",
    "content": "#ifndef INC_STM32F4EXTI\n#define INC_STM32F4EXTI\n#include <unicore-mx/cm3/common.h>\n#include <unicore-mx/stm32/f4/exti.h>\n\nint exti_register(uint32_t base, uint16_t pin, uint8_t trigger, void (*isr)(void *), void *isr_arg);\nvoid exti_unregister(int pin);\nint exti_enable(int idx, int enable);\nvoid exti_init(void);\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/fbcon.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"poll.h\"\n#include \"framebuffer.h\"\n#include \"fonts.h\"\n\nstatic uint32_t fbcon_l, fbcon_h;\nstatic uint32_t screen_rows, screen_cols;\n\n#define COLOR_DEFAULT 15 /* White */\n\nstruct dev_fbcon {\n    struct device *dev;\n    uint16_t sid;\n    uint16_t size_x;\n    uint16_t size_y;\n    uint16_t cursor;\n    uint8_t color;\n    uint8_t escape;\n    unsigned char *buffer;\n    unsigned char *colormap;\n    unsigned char *screen;\n};\n\nstatic int devfbcon_write(struct fnode *fno, const void *buf, unsigned int len);\nstatic int devfbcon_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int devfbcon_poll(struct fnode *fno, uint16_t events, uint16_t *revents);\nstatic void devfbcon_tty_attach(struct fnode *fno, int pid);\nstatic int devfbcon_seek(struct fnode *fno, int off, int whence);\n\n\nextern const uint32_t xterm_cmap[256];\n\nstatic struct module mod_devfbcon = {\n    .family = FAMILY_FILE,\n    .name = \"fbcon\",\n    .ops.open = device_open,\n    .ops.read = devfbcon_read,\n    .ops.poll = devfbcon_poll,\n    .ops.write = devfbcon_write,\n    .ops.seek = devfbcon_seek,\n    .ops.tty_attach = devfbcon_tty_attach,\n};\n\n\nstatic void devfbcon_tty_attach(struct fnode *fno, int pid)\n{\n    struct dev_fbcon *fbcon = (struct dev_fbcon *)FNO_MOD_PRIV(fno, &mod_devfbcon);\n    if (fbcon->sid != pid) {\n        //kprintf(\"/dev/%s active job pid: %d\\r\\n\", fno->fname, pid);\n        fbcon->sid = pid;\n    }\n}\n\nstatic void render_row(struct dev_fbcon *fbcon, int row)\n{\n    int i, j, l;\n    unsigned char fc;\n    const unsigned char *fcl;\n    uint8_t fc_color = COLOR_DEFAULT;\n    int screen_off;\n\n    for (i = 0; i < fbcon_l; i++) {            /* Each char ... i = column */ \n        fc = fbcon->buffer[row * fbcon_l + i]; /* fc = char to render */\n        fc_color = \n            fbcon->colormap[row * fbcon_l + i];/* fc_color: char color */\n        fcl = fb_font[fc];                     /* fcl = font rendering, 8 bytes. */\n        for (l = 0; l < FONT_HEIGHT; l++) {              /* screen lines 0..FONT_HEIGHT */\n            for (j = 0; j < FONT_WIDTH; j++) {          /* each pixel in screen line */\n                int right_shift = (FONT_HEIGHT - 1) - j;\n                screen_off = ((row * FONT_HEIGHT + l) * screen_cols) + (i * FONT_WIDTH) + j;\n                fbcon->screen[screen_off] = ((fcl[l] & (1 << (7 - j))))?fc_color:0;\n            }\n        }\n    }\n}\n\nstatic void render_screen(struct dev_fbcon *fbcon)\n{\n    int i;\n    for (i = 0; i < fbcon_h; i++)\n        render_row(fbcon, i);\n}\n\nstatic void scroll(struct dev_fbcon *fbcon)\n{\n    unsigned char *dest = fbcon->buffer;\n    unsigned char *src = fbcon->buffer + fbcon_l;\n    unsigned char *c_dest = fbcon->colormap;\n    unsigned char *c_src = fbcon->colormap + fbcon_l;\n    int i;\n    for (i = 0; i < fbcon_h; i++) {\n        memcpy(dest, src, fbcon_l);\n        dest += fbcon_l;\n        src += fbcon_l;\n        memcpy(c_dest, c_src, fbcon_l);\n        c_dest += fbcon_l;\n        c_src += fbcon_l;\n    }\n    fbcon->cursor = fbcon_l * (fbcon_h - 1);\n    memset(fbcon->buffer + fbcon->cursor, 0, fbcon_l);\n    memset(fbcon->colormap + fbcon->cursor, COLOR_DEFAULT, fbcon_l);\n}\n\nstatic int devfbcon_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    int i, j;\n    struct dev_fbcon *fbcon = (struct dev_fbcon *)FNO_MOD_PRIV(fno, &mod_devfbcon);\n    const uint8_t *cbuf = buf;\n\n    for (i = 0; i < len; i++) {\n        int p = 0, t = 0;\n        if ((fbcon->cursor) >= (fbcon_l * fbcon_h)) {\n            scroll(fbcon);\n        }\n\n        if (fbcon->escape == 0x1b) {\n            if (cbuf[i] == '[')\n                fbcon->escape = '[';\n            else { \n                fbcon->color = cbuf[i];\n                fbcon->escape = 0;\n            }\n            continue;\n        }\n        if (fbcon->escape == '[') {\n            if (cbuf[i] == 'H') {\n                fbcon->cursor = 0;\n            }\n            if (cbuf[i] == 'J') {\n                for (j = fbcon->cursor; j < (fbcon_l * fbcon_h); j++) {\n                    fbcon->buffer[j] = 0x20;\n                }\n            }\n            fbcon->escape = 0;\n            continue;\n        }\n        // TODO fbcon->color = cbuf[i];\n\n        switch(cbuf[i]) {\n            case '\\r':\n                fbcon->cursor -= (fbcon->cursor % fbcon_l);\n                break;\n\n            /* LF */\n            case '\\n': \n                fbcon->cursor += fbcon_l;\n                break;\n\n            /* FF */\n            case 0x0c:\n                memset(fbcon->buffer, 0, fbcon_l * fbcon_h);\n                fbcon->cursor = 0;\n                break;\n\n            /* TAB */\n            case '\\t': \n                t = fbcon->cursor % 4;\n                if (t == 0) \n                    t = 4;\n                for (p = 0; p < t; p++)\n                    fbcon->buffer[fbcon->cursor + p] = 0x20;\n                fbcon->cursor += t;\n                break;\n\n\n            /* BS */\n            case 0x08:\n                if (fbcon->cursor > 0) {\n                    fbcon->cursor--;\n                    fbcon->buffer[fbcon->cursor] = 0x20;\n                    fbcon->colormap[fbcon->cursor] = COLOR_DEFAULT;\n                }\n                break;\n\n\n            /* DEL */\n            case 0x7f:\n                fbcon->buffer[fbcon->cursor] = 0x20;\n                fbcon->colormap[fbcon->cursor] = COLOR_DEFAULT;\n                break;\n\n            /* ESC */\n            case 0x1b:\n                fbcon->escape = 0x1b;\n                break;\n\n            /* Printable char */\n            default:\n                fbcon->colormap[fbcon->cursor] = fbcon->color;\n                fbcon->buffer[fbcon->cursor++] = cbuf[i];\n        }\n    }\n    render_screen(fbcon);\n    return len;\n}\n\n\nstatic int devfbcon_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    return -EINVAL;\n}\n\n\nstatic int devfbcon_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    return 1;\n}\n\nstatic int devfbcon_seek(struct fnode *fno, int off, int whence)\n{\n    int new_off;\n    struct dev_fbcon *fbcon = (struct dev_fbcon *)FNO_MOD_PRIV(fno, &mod_devfbcon);\n    switch(whence) {\n        case SEEK_CUR:\n            new_off = fbcon->cursor + off;\n            break;\n        case SEEK_SET:\n            new_off = off;\n            break;\n        case SEEK_END:\n            new_off = fbcon_l * fbcon_h + off;\n            break;\n        default:\n            return -EINVAL;\n    }\n\n    if (new_off < 0)\n        new_off = 0;\n\n    if (new_off > fbcon_l * fbcon_h) {\n        new_off = fbcon_l * fbcon_h;\n    }\n    fbcon->cursor = new_off;\n    return 0;\n}\n\n\nconst char frosted_banner[] = \"\\r\\n~~~ Welcome to Frosted! ~~~\\r\\n\";\nconst char fbcon_banner[] = \"\\r\\nConsole framebuffer enabled.\\r\\n\";\n\nstatic const unsigned char color[2] = { 0x1b, 13 };\nstatic const unsigned char white[2] = { 0x1b, 15 };\n\nint fbcon_init(uint32_t cols, uint32_t rows)\n{\n    struct fnode *devfs = fno_search(\"/dev\");\n    struct dev_fbcon *fbcon = kalloc(sizeof(struct dev_fbcon));\n    struct fnode *fno_fbcon;\n\n    if (!fbcon)\n        return -1;\n\n    memset(fbcon, 0, sizeof(struct dev_fbcon));\n    screen_cols = cols;\n    screen_rows = rows;\n\n    fbcon_l = screen_cols / FONT_WIDTH;\n    fbcon_h = screen_rows / FONT_HEIGHT;\n\n    fbcon->buffer = u_malloc(fbcon_l * fbcon_h);\n    if (!fbcon->buffer) {\n        kfree(fbcon);\n        return -1;\n    }\n    fbcon->colormap = u_malloc(fbcon_l * fbcon_h);\n    if (!fbcon->colormap) {\n        kfree(fbcon->buffer);\n        kfree(fbcon);\n        return -1;\n    }\n\n    if (devfs == NULL) {\n        kfree(fbcon->colormap);\n        kfree(fbcon->buffer);\n        kfree(fbcon);\n        return -1;\n    }\n\n    memset(fbcon->buffer, 0, (fbcon_l * fbcon_h));\n    memset(fbcon->colormap, COLOR_DEFAULT, (fbcon_l * fbcon_h));\n    register_module(&mod_devfbcon);\n    fno_fbcon = fno_create(&mod_devfbcon, \"fbcon\", devfs);\n    fno_fbcon->priv = fbcon;\n    fbcon->size_x = fbcon_l;\n    fbcon->size_y = fbcon_h;\n    fbcon->screen = framebuffer_get();\n    fbcon->color = COLOR_DEFAULT;\n    framebuffer_setcmap(xterm_cmap);\n    /* Test */\n    devfbcon_write(fno_fbcon, color, 2);\n    devfbcon_write(fno_fbcon, frosted_banner, strlen(frosted_banner));\n    devfbcon_write(fno_fbcon, white, 2);\n    devfbcon_write(fno_fbcon, fbcon_banner, strlen(fbcon_banner));\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/fbcon.h",
    "content": "#ifndef FBCON_INCLUDED\n#define FBCON_INCLUDED\n\n#include <stdint.h>\n#include \"frosted.h\"\n\n#ifdef CONFIG_DEVFBCON\n/* kernel init */\nint fbcon_init(uint32_t cols, uint32_t rows);\n#else\n#  define fbcon_init(...) ((-ENOENT))\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/fonts.h",
    "content": "#ifndef INCLUDE_FONT_DEFINITION\n#define INCLUDE_FONT_DEFINITION\n\n#ifdef CONFIG_FONT_7x6\n#   define FONT_HEIGHT 7\n#   define FONT_WIDTH  6\n#endif\n\n#ifdef CONFIG_FONT_8x8\n#   define FONT_HEIGHT 8\n#   define FONT_WIDTH  8\n#endif\n\nextern const unsigned char fb_font[256][FONT_HEIGHT];\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/fortuna.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Alexander Wood, brabo\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include \"crypto/misc.h\"\n#include \"crypto/aes.h\"\n#include \"crypto/sha256.h\"\n#include \"fortuna.h\"\n#include <stdint.h>\n#include <sys/ioctl.h>\n\n/* Fortuna architecture defines */\n#define FORTUNA_POOL_COUNT            1\n#define FORTUNA_MINIMUM_RESEED_MS     100\n#define FORTUNA_MINIMUM_RESEED_ENTR   1\n#define FORTUNA_MAX_REQUEST_BYTES     1048576\n\nstruct fortuna_counter {\n    uint8_t values[16]; /* Fortuna requires a 128-bit counter */\n\n};\n\n/* Internal generator state */\nstruct fortuna_generator_state {\n\t/* Fortuna internals */\n\tuint8_t *key; /* 32 byte key */\n\tstruct fortuna_counter *counter;\n\tSha256 *pool;\n\tunsigned int last_reseed_time;\n\n\t/* AES and SHA internal stuff */\n\tAes *aes;\n\tSha256 *sha;\n};\n\nstruct fortuna_generator_state fortuna_generator = {};\n\n/* Internal helper functions */\nstatic int fortuna_extract_seed(uint8_t *seed_buffer, int buffer_size);\nstatic int fortuna_reseed(uint8_t *seed, uint8_t seed_size);\nstatic int fortuna_generate_block(uint8_t *buffer, int buffer_size);\n\nstatic inline void fortuna_init_counter(struct fortuna_counter *counter) {\n\tint i;\n\n\tfor (i = 0; i < 16; i++) {\n\t\tcounter->values[i] = 0;\n\n\t}\n\n}\n\nstatic inline void fortuna_increment_counter(struct fortuna_counter *counter) {\n\tint i;\n\n\tfor (i = 0; i < 16; i++) {\n\t\tif (counter->values[i] < 0xFF) { /* Not at maximum value */\n\t\t\tcounter->values[i]++;\n\t\t\treturn; /* Only return once we've found one not ready to overflow */\n\n\t\t} else {\n\t\t\tcounter->values[i] = 0;\n\n\t\t}\n\n\t}\n\n}\n\nstatic int fortuna_counter_is_zero(struct fortuna_counter *counter) {\n\tint i;\n\n\tfor (i = 0; i < 16; i++) {\n\t\tif (counter->values[i] != 0) {\n\t\t\treturn 0;\n\n\t\t}\n\n\t}\n\n\treturn 1; /* None of the individual values are non-zero, so... */\n\n}\n\n/* Prepare a seed from the selected pools. Helper function for re-seeding. */\nstatic int fortuna_extract_seed(uint8_t *seed_buffer, int buffer_size)\n{\n\tint i = 0;\n\tint hashes_added = 0;\n\n\tfor (i = 0; i < FORTUNA_POOL_COUNT; i++) {\n\t\tif (((i % 8) == 0) || (fortuna_generator.counter->values[0] & (1 << ((i - 1) % 8)))) {\n\t\t\t/* Use nth pool every (2^n)th reseed (so p1 every other time, p2 every 4th... */\n\t\t\tif ((hashes_added + 1) * FORTUNA_HASH_SIZE <= buffer_size) {\n\t\t\t\t/* Extract final hash for given pool, and put in appropriate part of seed buffer */\n\t\t\t\twc_Sha256Final(&(fortuna_generator.pool[i]), seed_buffer + (FORTUNA_HASH_SIZE * hashes_added));\n\t\t\t\thashes_added++;\n\t\t\t} else {\n\t\t\t\t/* Buffer not big enough */\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (hashes_added * FORTUNA_HASH_SIZE); /* Actual size of seed */\n}\n\n/* Re-seed the generator. Called when enough data has been used from the current 'run' */\nstatic int fortuna_reseed(uint8_t *seed, uint8_t seed_size)\n{\n\tuint8_t *sha_input = NULL;\n\n\tsha_input = (uint8_t *)kalloc(seed_size + FORTUNA_ENCRYPT_KEY_SIZE); /* Seed size + 256b of current SHA hash key */\n\n\tif (NULL == sha_input) {\n\t\t/* Failed to alloc, don't increment counter */\n\t\treturn 0;\n\t} else {\n\t\tmemcpy(sha_input, fortuna_generator.key, FORTUNA_ENCRYPT_KEY_SIZE); /* Current key */\n\t\tmemcpy(sha_input + FORTUNA_ENCRYPT_KEY_SIZE, seed, seed_size); /* New seed */\n\t}\n\n\twc_InitSha256(fortuna_generator.sha);\n\twc_Sha256Update(fortuna_generator.sha, sha_input, seed_size + 32);\n\twc_Sha256Final(fortuna_generator.sha, fortuna_generator.key);\n\n\tfortuna_increment_counter(fortuna_generator.counter);\n\n\tkfree(sha_input);\n\n\treturn 1;\n}\n\n/* Generate blocks of random data. Underlying function used by the user-callable random data functions. */\nstatic int fortuna_generate_block(uint8_t *buffer, int buffer_size)\n{\n\tuint8_t encrypt_iv[FORTUNA_ENCRYPT_IV_SIZE] = { 0 }; /* Can't use ECB mode and combine it with our external counter, so doing it this way */\n\n\t/* Run encryption block */\n\tif (!fortuna_counter_is_zero(fortuna_generator.counter)) { /* Refuse if not seeded */\n\t\tif (buffer_size >= FORTUNA_ENCRYPT_BLOCK_SIZE) {\n\t\t\twc_AesSetKey(fortuna_generator.aes, fortuna_generator.key, FORTUNA_ENCRYPT_KEY_SIZE, encrypt_iv, AES_ENCRYPTION);\n\t\t\twc_AesCbcEncrypt(fortuna_generator.aes, buffer, (const byte *)fortuna_generator.counter, FORTUNA_ENCRYPT_IV_SIZE);\n\n\t\t\tfortuna_increment_counter(fortuna_generator.counter);\n\n\t\t\treturn 1; /* Done succesfully */\n\t\t}\n\n\t\t/* Buffer size smaller than block size! */\n\t\treturn 0;\n\t} else {\n\t\t/* Not seeded, cannot produce anything! */\n\t\treturn 0;\n\t}\n}\n\n/* Public Fortuna functions */\n/* Sets up the generator */\nint fortuna_init(void)\n{\n\tint i = 0;\n\n\tfortuna_generator.key = kalloc(sizeof(uint8_t) * FORTUNA_ENCRYPT_KEY_SIZE);\n\tfortuna_generator.pool = kalloc(sizeof(Sha256) * FORTUNA_POOL_COUNT); /* n pools of strings; in practice, hashes iteratively updated */\n\tfortuna_generator.counter = kalloc(sizeof(struct fortuna_counter));\n\n\tfortuna_generator.aes = kalloc(sizeof(Aes));\n\tfortuna_generator.sha = kalloc(sizeof(Sha256));\n\n\tif (NULL == fortuna_generator.key  ||\n\t\tNULL == fortuna_generator.pool ||\n\t\tNULL == fortuna_generator.aes  ||\n\t\tNULL == fortuna_generator.sha) {\n\t\treturn -1; /* Failed to allocate memory! */\n\t}\n\n\t/* Set counter to 0 (also indicates unseeded state) */\n\tfortuna_init_counter(fortuna_generator.counter);\n\n\tfor (i = 0; i < FORTUNA_POOL_COUNT; i++) {\n\t\twc_InitSha256(&(fortuna_generator.pool[i])); /* TODO right? What does this look like in assembly? */\n\t}\n\n\treturn 0;\n}\n\n/* Add some entropy to a given pool TODO why need source IDs? */\nvoid fortuna_accu(int source, int pool, uint8_t *data, int data_size)\n{\n\t/* To be safe, but should avoid needing to do this, as it'll favour lower pools... */\n\tpool = pool % FORTUNA_POOL_COUNT;\n\n\t/* Add the new entropy data to the specified pool */\n\twc_Sha256Update(&(fortuna_generator.pool[pool]), data, data_size);\n}\n\n/* Get some random bytes from the generator. */\nint fortuna_get_bytes(uint8_t *buffer, int count)\n{\n\tint remaining_bytes = 0;\n\tuint8_t *block_buffer = 0;\n\tuint8_t *seed_buffer = 0;\n\tint blocks_done = 0;\n\tint seed_size = 0;\n\n\tif ((count > 0) && (count < (2 * 1024 * 1024))) {\n\t\t// probably we need to initialize and update fortuna_generator.last_reseed_time?\n\t\tif ((jiffies - fortuna_generator.last_reseed_time >= FORTUNA_MINIMUM_RESEED_MS) &&\n\t\t\t(1 >= FORTUNA_MINIMUM_RESEED_ENTR)) { /* FIXME to check 'size' of pool 0 */\n\t\t\tseed_buffer = kalloc(sizeof(uint8_t) * FORTUNA_POOL_COUNT * FORTUNA_HASH_SIZE); /* Assume that we use every pool hash... */\n\n\t\t\tif (NULL == seed_buffer) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tseed_size = fortuna_extract_seed(seed_buffer, (sizeof(uint8_t) * FORTUNA_POOL_COUNT * FORTUNA_HASH_SIZE));\n\t\t\tfortuna_reseed(seed_buffer, seed_size);\n\t\t\tkfree(seed_buffer);\n\t\t}\n\n\t\t/* Get random blocks until we have our data. */\n\t\tfor (remaining_bytes = count; remaining_bytes > 0; remaining_bytes -= FORTUNA_ENCRYPT_BLOCK_SIZE) {\n\t\t\tif (remaining_bytes / FORTUNA_ENCRYPT_BLOCK_SIZE > 0) { /* At least one full block remaining? Can copy directly without overflowing. */\n\t\t\t\tfortuna_generate_block(buffer + (FORTUNA_ENCRYPT_BLOCK_SIZE * blocks_done++), FORTUNA_ENCRYPT_BLOCK_SIZE); /* TODO check! */\n\t\t\t} else {\n\t\t\t\t/* This'll only be necessary for the last block, and only if requested byte count != multiple of block size */\n\t\t\t\tblock_buffer = kalloc(FORTUNA_ENCRYPT_BLOCK_SIZE);\n\n\t\t\t\tif (NULL != block_buffer) {\n\t\t\t\t\tfortuna_generate_block(block_buffer, FORTUNA_ENCRYPT_BLOCK_SIZE);\n\n\t\t\t\t\t/* Copy required part of block to output */\n\t\t\t\t\tmemcpy(buffer + (blocks_done * FORTUNA_ENCRYPT_BLOCK_SIZE),\n\t\t\t\t\tblock_buffer, remaining_bytes);\n\n\t\t\t\t\tkfree(block_buffer);\n\n\t\t\t\t} else {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn 1;\n\t} else {\n\t\t/* Not allowed to produce more than 1MiB of data at once */\n\t\treturn 0;\n\t}\n}\n\nvoid fortuna_shutdown(void)\n{\n\t/* Don't just PICO_FREE them, otherwise generator internals still available in RAM! */\n\t/* If we're going to set it to something, might as well be 10101010, in case there're any weird electrical effects making it easy to detect was-1s or was-0s or something */\n\tmemset(fortuna_generator.key, 0x55, (sizeof(uint8_t) * 32));\n\tmemset(fortuna_generator.counter, 0x55, (sizeof(struct fortuna_counter)));\n\tmemset(fortuna_generator.pool, 0x55, (sizeof(Sha256) * FORTUNA_POOL_COUNT));\n\tmemset(fortuna_generator.aes, 0x55, (sizeof(Aes)));\n\tmemset(fortuna_generator.sha, 0x55, (sizeof(Sha256)));\n\n\tkfree(fortuna_generator.key);\n\tkfree(fortuna_generator.counter);\n\tkfree(fortuna_generator.pool);\n\tkfree(fortuna_generator.aes);\n\tkfree(fortuna_generator.sha);\n}\n"
  },
  {
    "path": "kernel/drivers/framebuffer.h",
    "content": "#ifndef FRAMEBUFFER_INCLUDED\n#define FRAMEBUFFER_INCLUDED\n\n#include <stdint.h>\n#include \"frosted.h\"\n#include <sys/frosted-io.h>\n\nstruct fb_ops;\n\n\nstruct fb_info {\n        struct fb_var_screeninfo var;   /* Current var */\n        //struct fb_fix_screeninfo fix;   /* Current fix */\n        struct fb_videomode *mode;      /* current mode */\n        //struct backlight_device *bl_dev;\n\n        struct fb_ops *fbops;\n        struct device *dev;             /* This is this fb device */\n        uint8_t *screen_buffer;   /* Framebuffer address */\n};\n\nstruct fb_ops {\n        /* open/release and usage marking */\n        int (*fb_open)(struct fb_info *info);\n        int (*fb_release)(struct fb_info *info);\n\n        /* checks var and eventually tweaks it to something supported,\n         * DO NOT MODIFY PAR */\n        int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);\n\n        /* set the video mode according to info->var */\n        int (*fb_set_par)(struct fb_info *info);\n\n        /* set color registers in batch */\n        int (*fb_setcmap)(uint32_t *cmap, struct fb_info *info);\n\n        /* blank display */\n        int (*fb_blank)(struct fb_info *info);\n\n        /* Draws a rectangle */\n        //void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);\n        /* Copy data from area to another */\n        //void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);\n        /* Draws a image to the display */\n        //void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);\n\n        /* Draws cursor */\n        //int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);\n\n        /* Rotates the display */\n        //void (*fb_rotate)(struct fb_info *info, int angle);\n\n        /* perform fb specific ioctl (optional) */\n        int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, unsigned long arg);\n\n        /* teardown any resources to do with this framebuffer */\n        void (*fb_destroy)(struct fb_info *info);\n};\n\n\n#ifdef CONFIG_DEVFRAMEBUFFER\n/* low-level drivers must call this register function first */\nint register_framebuffer(struct fb_info *fb_info);\n\n/* Higher level drivers may access fb screen directly */\nunsigned char *framebuffer_get(void);\nint framebuffer_setcmap(uint32_t *cmap);\n\n/* kernel init */\nint fb_init(void);\n#else\n#  define register_framebuffer(...) ((-ENOENT))\n#  define fb_init() ((-ENOENT))\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/frand.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: brabo\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include \"frand.h\"\n#include \"fortuna.h\"\n#include \"rng.h\"\n#include <stdint.h>\n#include <sys/ioctl.h>\n\n#if defined(STM32F2) || defined(STM32F4) || defined(STM32F7)\n#   include \"unicore-mx/stm32/rng.h\"\n#endif\n\n#define MAX_FRANDS         (1)\n\nextern uint32_t req;\n\nstatic struct frand_info *frand[MAX_FRANDS] = { 0 };\n\nstatic int frand_open(const char *path, int flags);\nstatic int frand_read(struct fnode *fno, void *buf, unsigned int len);\n\nstatic struct module mod_devfrand = {\n    .family = FAMILY_FILE,\n    .name = \"frand\",\n    .ops.open = frand_open,\n    .ops.read = frand_read,\n};\n\nstatic int frand_open(const char *path, int flags)\n{\n\tstruct fnode *f = fno_search(path);\n\n\tif (!f)\n\t\treturn -1;\n\n\treturn device_open(path, flags);\n}\n\nstatic int frand_read(struct fnode *fno, void *buf, unsigned int len)\n{\n\tstruct frand_info *frand;\n\n\tif (len == 0)\n\t\treturn len;\n\n\tfrand = (struct frand_info *)FNO_MOD_PRIV(fno, &mod_devfrand);\n\tif (!frand)\n\t\treturn -1;\n\n\t// mutex_lock(fb->dev->mutex);\n\n\tfortuna_get_bytes(buf, len);\n\treq += len;\n\trng_enable_interrupt();\n\n\t//mutex_unlock(fb->dev->mutex);\n\treturn len;\n}\n\n\nstatic int frand_fno_init(struct fnode *dev, struct frand_info *frand)\n{\n\tstatic int num_frand = 0;\n\tchar name[7] = \"frand\";\n\n\tif (!frand)\n\t\treturn -1;\n\n\tname[6] =  '0' + num_frand++;\n\n\tfrand->dev = device_fno_init(&mod_devfrand, name, dev, FL_TTY, frand);\n\n\treturn 0;\n}\n\nvoid frand_init(struct fnode *dev)\n{\n\t/* Ony one FRAND supported for now */\n\tfrand_fno_init(dev, frand[0]);\n}\n\n/* Register a low-level frand driver */\nint register_frand(struct frand_info *frand_info)\n{\n\tif (!frand_info)\n\t\treturn -1;\n\n\tif (!frand_info->frandops)\n\t\treturn -1;\n\n\tif (frand_info->frandops->frand_open)\n\t\tfrand_info->frandops->frand_open(frand_info);\n\n\tfrand[0] = frand_info;\n\n\tregister_module(&mod_devfrand);\n\tfortuna_init();\n\n\treturn 0;\n}\n\n"
  },
  {
    "path": "kernel/drivers/ft5336.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera <root@danielinux.net>\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"cirbuf.h\"\n#include \"dma.h\"\n#include \"cirbuf.h\"\n#include \"i2c.h\"\n\n#define FT5336_I2C_ADDR (0x70)\n#define MAX_W   (480)\n#define MAX_H   (272)\n\n#define FT5336_MODE         (0x00)\n#define FT5336_GESTURE_ID   (0x01)\n#define FT5336_TOUCHDATA    (0x02)\n#   define TD_PRESS         (0x00)\n#   define TD_RELEASE       (0x01)\n#   define TD_CONTACT       (0x02)\n#define FT5336_P1_XH        (0x03)\n#define FT5336_P1_YH        (0x05)\n\n#define FT5336_G_MODE       (0xA4)\n#define FT5336_G_MODE_INTERRUPT (0x01)\n\n#define FT5336_CHIP_ID      (0xA8)\n#define FT5336_CHIP_ID_VAL  (0x51)\n\n/* Single device supported in this driver. */\n#define ST_OFF 0\n#define ST_RDY 1\n#define ST_ON  2\n\n\nstruct dev_ts {\n    struct i2c_slave i2c;\n    struct device *dev;\n    uint8_t i2c_data;\n    int state;\n} Ts;\n\n\n\n/* Module description */\nint ft5336_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    return 0;\n}\n\nstatic struct module mod_devts = {\n    .family = FAMILY_FILE,\n    .name = \"ts\",\n    .ops.open = device_open,\n    .ops.read = ft5336_read\n};\n\n\nstatic void ft5336_task(void *arg)\n{\n    (void)arg;\n    uint8_t val;\n\n    if (i2c_kthread_read(&Ts.i2c, FT5336_CHIP_ID, &val, 1) > 0) {\n        if (val != FT5336_CHIP_ID_VAL)\n            return 0; /* kthread terminated. */\n    }\n    \n    val = FT5336_G_MODE_INTERRUPT;\n    i2c_kthread_write(&Ts.i2c, FT5336_G_MODE, &val, 1);\n}\n\nint ft5336_init(uint32_t bus)\n{\n    int i;\n    struct fnode *devdir = fno_search(\"/dev\");\n    if (!devdir)\n        return -ENOENT;\n    memset(&Ts, 0, sizeof(struct dev_ts));\n    Ts.dev = device_fno_init(&mod_devts, \"ts\", devdir, 0, &Ts);\n\n    /* Populate i2c_slave struct */\n    Ts.i2c.bus = bus;\n    Ts.i2c.address = FT5336_I2C_ADDR;\n    kthread_create(ft5336_task, NULL);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/gpio.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include \"gpio.h\"\n#include <stdint.h>\n#include \"ioctl.h\"\n#include \"poll.h\"\n\n\n#include \"sys/frosted-io.h\"\n\n#if defined(STM32F4) || defined(STM32F7)\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/cm3/nvic.h>\n\nstatic inline uint32_t ARCH_GPIO_BASE(int x)\n{\n    switch(x) {\n        case 1:\n            return GPIOA;\n        case 2:\n            return GPIOB;\n        case 3:\n            return GPIOC;\n        case 4:\n            return GPIOD;\n        case 5:\n            return GPIOE;\n        case 6:\n            return GPIOF;\n        case 7:\n            return GPIOG;\n        case 8:\n            return GPIOH;\n        case 9:\n            return GPIOI;\n        case 10:\n            return GPIOJ;\n        case 11:\n            return GPIOK;\n        default:\n            return 0;\n    }\n}\n#define ARCH_GPIO_PIN(X) (1 << X)\n#define ARCH_GPIO_BASE_MAX 31\n#define ARCH_GPIO_PIN_MAX 15\n\n\n#include \"exti.h\"\n#endif\n\n#ifdef STM32F7\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/cm3/nvic.h>\n#endif\n\n#if defined(NRF51) || defined(NRF52)\n#include <unicore-mx/nrf/gpio.h>\n\nstatic inline uint32_t ARCH_GPIO_BASE(int x)\n{\n    return GPIO_BASE;\n}\n\n#define ARCH_GPIO_PIN(X) (1 << X)\n#define ARCH_GPIO_BASE_MAX 1\n#define ARCH_GPIO_PIN_MAX 31\n\n\nint exti_register(uint32_t base, uint16_t pin, uint8_t trigger, void (*isr)(void *), void *isr_arg) {\n\n}\nvoid exti_unregister(int pin) {\n\n}\nint exti_enable(int idx, int enable) {\n\n}\nvoid exti_init(void) {\n\n}\n\n#endif\n#ifdef LPC17XX\n#include <unicore-mx/lpc17xx/nvic.h>\n#include <unicore-mx/lpc17xx/pwr.h>\n#include <unicore-mx/lpc17xx/gpio.h>\n#include <unicore-mx/lpc17xx/exti.h>\nstatic inline uint32_t ARCH_GPIO_BASE(int x)\n{\n    switch(x) {\n        case 1:\n            return GPIO1;\n        case 2:\n            return GPIO2;\n        case 3:\n            return GPIO3;\n        case 4:\n            return GPIO4;\n        default:\n            return 0;\n    }\n}\n#define ARCH_GPIO_PIN(X) (1 << X)\n#define ARCH_GPIO_BASE_MAX 4\n#define ARCH_GPIO_PIN_MAX 32\n#endif\n\n\n\n#ifdef PYBOARD\n# define LED0 \"gpio_1_13\"\n# define LED1 \"gpio_1_14\"\n# define LED2 \"gpio_1_15\"\n# define LED3 \"gpio_1_4\"\n#elif defined (STM32F7)\n# define LED0 \"gpio_9_1\"\n# define LED1 \"\"\n# define LED2 \"\"\n# define LED3 \"\"\n#elif defined (STM32F4)\n# if defined (F429DISCO)\n#  define LED0 \"gpio_6_13\"\n#  define LED1 \"gpio_6_14\"\n# else\n#  define LED0 \"gpio_3_12\"\n#  define LED1 \"gpio_3_13\"\n#endif\n# define LED2 \"gpio_3_14\"\n# define LED3 \"gpio_3_15\"\n#elif defined (LPC17XX)\n#if 0\n/*LPCXpresso 1769 */\n# define LED0 \"/dev/gpio_0_22\"\n# define LED1 \"/dev/null\"\n# define LED2 \"/dev/null\"\n# define LED3 \"/dev/null\"\n#else\n/* mbed 1768 */\n# define LED0 \"gpio_1_18\"\n# define LED1 \"gpio_1_20\"\n# define LED2 \"gpio_1_21\"\n# define LED3 \"gpio_1_23\"\n#endif\n#else\n# define LED0 \"null\"\n# define LED1 \"null\"\n# define LED2 \"null\"\n# define LED3 \"null\"\n#endif\n#include \"gpio.h\"\n\nstruct dev_gpio *Gpio_list = NULL;\nstruct dev_gpio *Gpio_list_tail = NULL;\n\nstatic void gpio_list_add(struct dev_gpio *pio)\n{\n    pio->next = NULL;\n    if (!Gpio_list) {\n        Gpio_list = pio;\n        Gpio_list_tail = pio;\n    } else {\n        Gpio_list_tail->next = pio;\n        Gpio_list_tail = pio;\n    }\n}\n\nstatic struct dev_gpio *gpio_list_find(uint32_t base, uint32_t pin)\n{\n    struct dev_gpio *cur = Gpio_list;\n    while(cur) {\n        if ((cur->base == base) && (cur->pin == pin))\n            return cur;\n        cur = cur->next;\n    }\n    return NULL;\n}\n\nstatic void gpio_list_del(struct dev_gpio *old)\n{\n    struct dev_gpio *cur = Gpio_list;\n    struct dev_gpio *last = NULL;\n    while(cur) {\n        if (cur == old) {\n            if (last == NULL)\n                Gpio_list = cur->next;\n            else\n                last->next = cur->next;\n            if (Gpio_list_tail == cur)\n                Gpio_list_tail = last;\n            return;\n        }\n        last = cur;\n        cur = cur->next;\n    }\n}\n\nint gpio_list_len(void)\n{\n    int len = 0;\n    struct dev_gpio *l = Gpio_list;\n\n    while(l) {\n        len++;\n        l = l->next;\n    }\n    return len;\n}\n\nstatic int devgpio_write(struct fnode *fno, const void *buf, unsigned int len);\nstatic int devgpio_ioctl(struct fnode *fno, const uint32_t cmd, void *arg);\nstatic int devgpio_read (struct fnode *fno, void *buf, unsigned int len);\nstatic int devgpio_poll (struct fnode *fno, uint16_t events, uint16_t *revents);\nstatic int devgpio_close (struct fnode *fno);\n\nstatic int devgpiomx_ioctl(struct fnode * fno, const uint32_t cmd, void *arg);\n\nstatic struct module mod_devgpio = {\n    .family = FAMILY_FILE,\n    .name = \"gpio\",\n    .ops.open = device_open,\n    .ops.read = devgpio_read,\n    .ops.poll = devgpio_poll,\n    .ops.write = devgpio_write,\n    .ops.ioctl = devgpio_ioctl,\n    .ops.close = devgpio_close,\n};\n\nstatic struct module mod_devgpio_mx = {\n    .family = FAMILY_FILE,\n    .name = \"gpio-mx\",\n    .ops.ioctl = devgpiomx_ioctl,\n};\n\n\n/****************/\n/* HW specifics */\n/****************/\n\n/* LM3S */\n#ifdef LM3S\n#endif\n\n\n\n/* STM32 */\n#if defined(STM32F4) || defined(STM32F7)\n#define GPIO_CLOCK_ENABLE(P)       switch(P){    \\\n                                                                case GPIOA:rcc_periph_clock_enable(RCC_GPIOA);  break;  \\\n                                                                case GPIOB:rcc_periph_clock_enable(RCC_GPIOB);  break;  \\\n                                                                case GPIOC:rcc_periph_clock_enable(RCC_GPIOC);  break;  \\\n                                                                case GPIOD:rcc_periph_clock_enable(RCC_GPIOD);  break;  \\\n                                                                case GPIOE:rcc_periph_clock_enable(RCC_GPIOE);  break;  \\\n                                                                case GPIOF:rcc_periph_clock_enable(RCC_GPIOF);  break;  \\\n                                                                case GPIOG:rcc_periph_clock_enable(RCC_GPIOG);  break;  \\\n                                                                case GPIOH:rcc_periph_clock_enable(RCC_GPIOH);  break;  \\\n                                                                case GPIOI:rcc_periph_clock_enable(RCC_GPIOI);  break;  \\\n                                                                case GPIOJ:rcc_periph_clock_enable(RCC_GPIOJ);  break;  \\\n                                                                case GPIOK:rcc_periph_clock_enable(RCC_GPIOK);  break;  \\\n                                                                }\n\n#define SET_INPUT(P, D, I)               gpio_mode_setup(P, GPIO_MODE_INPUT, D, I);\n\n#define SET_OUTPUT(P, I, O, S)     gpio_mode_setup(P, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, I);   \\\n                                                          gpio_set_output_options(P, O, S, I);\n\n#define SET_AF(P, M, A, I, O, S)              gpio_mode_setup(P, M, GPIO_PUPD_NONE, I);  \\\n                                                         gpio_set_output_options(P, O, S, I); \\\n                                                         gpio_set_af(P, A, I);\n\n\n#endif\n\n/* NRF */\n#if defined(NRF51) || defined(NRF52)\n#define GPIO_CLOCK_ENABLE(C)\n#define SET_INPUT(P, D, I)               gpio_mode_setup(P, GPIO_MODE_INPUT, D, I);\n\n#define SET_OUTPUT(P, I, O, S)     gpio_mode_setup(P, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, I);\n#endif\n\n/* LPC */\n#ifdef LPC17XX\n#define GPIO_CLOCK_ENABLE(C)                pwr_enable_peripherals(PWR_PCONP_GPIO);\n\n#define SET_INPUT(P, D, I)                  gpio_mode_setup(P, GPIO_MODE_INPUT, D, I);    \\\n                                                               gpio_set_af(P, GPIO_AF0, I);\n\n#define SET_OUTPUT(P, I, O, S)          gpio_mode_setup(P, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, I);   \\\n                                                                gpio_set_af(P, GPIO_AF0, I);\n\n#define SET_AF(P, M, A, I, O, S)                   gpio_mode_setup(P, M, GPIO_PUPD_NONE, I);    \\\n                                                                gpio_set_af(P, A, I);\n\nvoid eint_isr(uint32_t exti_base)\n{\n    /* What next? */\n    exti_clear_flag(exti_base);\n}\nvoid eint0_isr(void)\n{\n    eint_isr(EXTI0);\n}\nvoid eint1_isr(void)\n{\n    eint_isr(EXTI1);\n}\nvoid eint2_isr(void)\n{\n    eint_isr(EXTI2);\n}\nvoid eint3_isr(void)\n{\n    eint_isr(EXTI3);\n}\n\n#endif\n\n\nstatic void gpio_isr(void *arg)\n{\n    struct dev_gpio *gpio = arg;\n    if (gpio->trigger)\n        exti_enable(gpio->exti_idx, 0);\n    if (gpio->dev->task != NULL) {\n        task_resume(gpio->dev->task);\n    }\n}\n\nstatic int gpio_set_trigger(struct dev_gpio *gpio, uint32_t trigger)\n{\n    uint32_t val = gpio_get(gpio->base, gpio->pin);\n    gpio->trigger = (uint8_t) trigger;\n    RESET_TRIGGER_WAITING(gpio);\n    if (trigger == GPIO_TRIGGER_TOGGLE) {\n        if (val)\n            SET_TRIGGER_WAITING(gpio, GPIO_TRIGGER_FALL);\n        else\n            SET_TRIGGER_WAITING(gpio, GPIO_TRIGGER_RAISE);\n    } else {\n        SET_TRIGGER_WAITING(gpio, trigger);\n    }\n    if (trigger) \n        return exti_register(gpio->base, gpio->pin, gpio->trigger, gpio_isr, gpio);\n    else\n        return 0;\n}\n\nstatic int devgpiomx_ioctl(struct fnode * fno, const uint32_t cmd, void *arg)\n{\n    struct dev_gpiomx *gpiomx;\n    struct gpio_req *req = arg;\n    struct gpio_config addr = { };\n\n    if ((req->base == 0) || (req->pin == 0))\n        return -EINVAL;\n\n    if ((req->base > ARCH_GPIO_BASE_MAX) || (req->pin > ARCH_GPIO_PIN_MAX))\n        return -EINVAL;\n\n    addr.base = ARCH_GPIO_BASE(req->base);\n    addr.pin = ARCH_GPIO_PIN(req->pin);\n    addr.pullupdown = GPIO_PUPD_NONE;\n\n    if (cmd == IOCTL_GPIOMX_CREATE) {\n        if (gpio_list_find(addr.base, addr.pin))\n            return -EEXIST;\n        addr.name = req->name;\n        gpio_create(&mod_devgpio, &addr );\n        return 0;\n    }\n    if (cmd == IOCTL_GPIOMX_DESTROY) {\n        return 0;\n    }\n    return -EINVAL;\n}\n\n\nstatic int devgpio_write(struct fnode * fno, const void *buf, unsigned int len)\n{\n    struct dev_gpio *gpio;\n    char *arg = (char *)buf;\n\n    gpio = (struct dev_gpio *)FNO_MOD_PRIV(fno, &mod_devgpio);\n    if(!gpio)\n        return -1;\n\n    if (arg[0] == '1') {\n        gpio_set(gpio->base, gpio->pin);\n        return 1;\n    } else if (arg[0] == '0') {\n        gpio_clear(gpio->base, gpio->pin);\n        return 1;\n    } else {\n        return -1;\n    }\n}\n\nstatic int devgpio_ioctl(struct fnode * fno, const uint32_t cmd, void *arg)\n{\n    struct dev_gpio *gpio;\n\n    gpio = (struct dev_gpio *)FNO_MOD_PRIV(fno, &mod_devgpio);\n    if(!gpio)\n        return -EEXIST;\n\n    /* (protected GPIOs cannot be reconfigured from userspace) */\n    if (IS_PROTECTED(gpio)) {\n        return -EPERM;\n    }\n\n    if (cmd == IOCTL_GPIO_ENABLE) {\n        return 0;\n    }\n    if (cmd == IOCTL_GPIO_DISABLE) {\n        return 0;\n    }\n    if (cmd == IOCTL_GPIO_SET_INPUT) {\n        SET_INPUT(gpio->base, GPIO_PUPD_NONE, gpio->pin);\n        return 0;\n    }\n    if (cmd == IOCTL_GPIO_SET_OUTPUT) {\n        SET_OUTPUT(gpio->base, gpio->pin, gpio->optype, gpio->speed);\n        return 0;\n    }\n    if (cmd == IOCTL_GPIO_SET_PULLUPDOWN) {\n        /* Setting pullup/down implies an input */\n        SET_INPUT(gpio->base, *((uint32_t*)arg), gpio->pin);\n        return 0;\n    }\n#ifdef GPIO_MODE_AF\n    if (cmd == IOCTL_GPIO_SET_ALT_FUNC) {\n        gpio_set_af(gpio->base, *((uint32_t*)arg), gpio->pin);\n        return 0;\n    }\n#endif\n    if (cmd == IOCTL_GPIO_SET_TRIGGER) {\n        uint32_t trigger = *((uint32_t *)arg);\n        if (trigger > GPIO_TRIGGER_TOGGLE) {\n            gpio->trigger = 0;\n            return -EINVAL;\n        }\n        gpio->exti_idx = gpio_set_trigger(gpio, trigger);\n        return 0;\n    }\n    return -EINVAL;\n}\n\nstatic int devgpio_read(struct fnode * fno, void *buf, unsigned int len)\n{\n    int out;\n    struct dev_gpio *gpio;\n    char *ptr = (char *)buf;\n    uint8_t val = 0;\n\n    gpio = (struct dev_gpio *)FNO_MOD_PRIV(fno, &mod_devgpio);\n    if(!gpio)\n        return -1;\n\n    /* GPIO: get current value */\n    val = gpio_get(gpio->base, gpio->pin);\n\n    if (gpio->trigger) {\n        if ((gpio->dev->task) && (gpio->dev->task != this_task())) {\n            return -EBUSY;\n        }\n        gpio->dev->task = this_task();\n        if ((gpio->trigger == GPIO_TRIGGER_NONE) ||\n                (val && (gpio->trigger == GPIO_TRIGGER_RAISE)) || (!val && (gpio->trigger == GPIO_TRIGGER_FALL))) {\n            /* Unlock immediately */\n            *((uint8_t*)buf) = val ? '1':'0';\n            gpio->dev->task = NULL;\n            return 1;\n        } else if (gpio->trigger == GPIO_TRIGGER_TOGGLE) {\n            if (TRIGGER_WAITING(gpio) == val) {\n                *((uint8_t*)buf) = val ? '1':'0';\n                RESET_TRIGGER_WAITING(gpio);\n                SET_TRIGGER_WAITING(gpio, (val) ? GPIO_TRIGGER_FALL : GPIO_TRIGGER_RAISE);\n                gpio->dev->task = NULL;\n                return 1;\n            }\n        }\n        task_suspend();\n        exti_enable(gpio->exti_idx, 1);\n        return SYS_CALL_AGAIN;\n    } else {\n        *((uint8_t*)buf) = val ? '1':'0';\n        return 1;\n    }\n}\n\n\nstatic int devgpio_poll(struct fnode * fno, uint16_t events, uint16_t *revents)\n{\n    int ret = 0;\n    struct dev_gpio *gpio = (struct dev_gpio *)FNO_MOD_PRIV(fno, &mod_devgpio);\n    if(!gpio)\n        return -EEXIST;\n    if (events & POLLOUT) {\n        *revents |= POLLOUT;\n        ret = 1;\n    }\n    if (events == POLLIN) {\n        uint8_t val;\n        if (gpio->trigger) {\n            if ((gpio->dev->task) && (gpio->dev->task != this_task())) {\n                return -EBUSY;\n            }\n            gpio->dev->task = this_task();\n            val = gpio_get(gpio->base, gpio->pin);\n            if ((val && (gpio->trigger == GPIO_TRIGGER_RAISE)) || (!val && (gpio->trigger == GPIO_TRIGGER_FALL))) {\n                ret = 1;\n                *revents |= POLLIN;\n            } else if ((gpio->trigger == GPIO_TRIGGER_TOGGLE) && (TRIGGER_WAITING(gpio) == val)) {\n                ret = 1;\n                *revents |= POLLIN;\n            }\n        } else {\n            ret = 1;\n            *revents |= POLLIN;\n        }\n    }\n    return ret;\n}\n\n\nstatic void gpio_fno_init(struct dev_gpio *g, const char *name)\n{\n    struct fnode *devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return;\n\n    g->dev = device_fno_init(&mod_devgpio, name, devfs, FL_RDWR, g);\n    g->base = g->base;\n    g->pin = g->pin;\n    if (strcmp(name, LED0) == 0)\n    {\n        char gpio_name[32] = \"/dev/\";\n        strcat(gpio_name, LED0);\n        vfs_symlink(gpio_name, \"/dev/led0\");\n    }\n    if (strcmp(name, LED1) == 0)\n    {\n        char gpio_name[32] = \"/dev/\";\n        strcat(gpio_name, LED1);\n        vfs_symlink(gpio_name, \"/dev/led1\");\n    }\n    if (strcmp(name, LED2) == 0)\n    {\n        char gpio_name[32] = \"/dev/\";\n        strcat(gpio_name, LED2);\n        vfs_symlink(gpio_name, \"/dev/led2\");\n    }\n    if (strcmp(name, LED3) == 0)\n    {\n        char gpio_name[32] = \"/dev/\";\n        strcat(gpio_name, LED3);\n        vfs_symlink(gpio_name, \"/dev/led3\");\n    }\n}\n\nint gpio_create(struct module *mod, const struct gpio_config *gpio_config)\n{\n    struct dev_gpio *gpio;\n    if(gpio_config->base == 0)\n        return -EINVAL;\n    gpio = kalloc(sizeof(struct dev_gpio));\n    if (!gpio)\n        return -ENOMEM;\n\n    memset(gpio, 0, sizeof(struct gpio_config));\n    gpio->base = gpio_config->base;\n    gpio->pin = gpio_config->pin;\n    gpio->mode = gpio_config->mode;\n    gpio->af = gpio_config->af;\n    gpio->speed = gpio_config->speed;\n    gpio->optype = gpio_config->optype;\n    gpio->pullupdown = gpio_config->pullupdown;\n    gpio->trigger = GPIO_TRIGGER_NONE;\n    if (gpio_config->name) {\n        gpio_fno_init(gpio, gpio_config->name);\n    }\n\n    if (mod)\n        gpio->owner = mod;\n    else\n        gpio->owner = &mod_devgpio;\n\n    if (gpio->owner != &mod_devgpio) {\n        gpio->flags |= GPIO_FL_PROTECTED;\n    } else {\n        gpio->flags &= ~GPIO_FL_PROTECTED;\n    }\n\n    GPIO_CLOCK_ENABLE(gpio_config->base);\n\n    switch(gpio_config->mode)\n    {\n        case GPIO_MODE_INPUT:\n            SET_INPUT(gpio_config->base, gpio_config->pullupdown, gpio_config->pin);\n            break;\n        case GPIO_MODE_OUTPUT:\n            SET_OUTPUT(gpio_config->base, gpio_config->pin, gpio_config->optype, gpio_config->speed);\n            break;\n#ifdef GPIO_MODE_AF\n        case GPIO_MODE_AF:\n            SET_AF(gpio_config->base, GPIO_MODE_AF, gpio_config->af,  gpio_config->pin, gpio_config->optype, gpio_config->speed);\n            break;\n#endif\n        case GPIO_MODE_ANALOG:\n            gpio_mode_setup(gpio_config->base, gpio_config->mode, GPIO_PUPD_NONE, gpio_config->pin);\n            break;\n    }\n    if (gpio_config->trigger > 0) {\n        gpio->exti_idx = gpio_set_trigger(gpio, gpio_config->trigger);\n    }\n    gpio_list_add(gpio);\n    return 0;\n}\n\nint gpio_init(void)\n{\n    static struct device *gpiomx_dev = NULL;\n    struct fnode *devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return -ENOENT;\n\n    gpiomx_dev = device_fno_init(&mod_devgpio_mx, \"gpiomx\", devfs, FL_RDWR, &mod_devgpio_mx);\n\n    register_module(&mod_devgpio);\n    register_module(&mod_devgpio_mx);\n    return 0;\n}\n\nstatic int devgpio_close(struct fnode *fno)\n{\n    struct dev_gpio *gpio = (struct dev_gpio *)FNO_MOD_PRIV(fno, &mod_devgpio);\n    if (gpio) {\n        gpio->dev->task = NULL;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/gpio.h",
    "content": "#ifndef INC_GPIO\n#define INC_GPIO\n#include \"frosted.h\"\n#include \"sys/frosted-io.h\"\n\n\n\n#if defined(STM32F4) || defined(STM32F7)\n#include <unicore-mx/stm32/gpio.h>\n#endif\n\n\nstruct gpio_config {\n    uint32_t base;\n    uint32_t pin;\n    uint32_t mode;\n    uint8_t pullupdown;\n    uint8_t speed;\n    uint8_t optype;\n    uint8_t af;\n    uint32_t trigger;\n    const char* name;\n};\n\n#define GPIO_FL_PROTECTED (0x10)\n#define SET_TRIGGER_WAITING(x,t) x->flags|=t\n#define RESET_TRIGGER_WAITING(x) x->flags&=0xFFFFFFF0\n#define TRIGGER_WAITING(x) (((x->flags & 0x0F) == GPIO_TRIGGER_RAISE)?1:0)\n\n#define IS_PROTECTED(x) ((x->flags & GPIO_FL_PROTECTED) == GPIO_FL_PROTECTED)\n\nstruct dev_gpio {\n    struct device *dev;\n    struct module *owner;  /* Module that registered the gpio */\n    uint32_t mode;\n    uint32_t af;\n    uint32_t base;\n    uint32_t pin;\n    uint8_t trigger;\n    int exti_idx;\n    unsigned int flags;\n    uint32_t optype;\n    uint32_t speed;\n    uint8_t pullupdown;\n    struct dev_gpio *next;\n};\n\nextern struct dev_gpio *Gpio_list;\n\nint gpio_init(void);\nint gpio_list_len(void);\nint gpio_create(struct module *mod, const struct gpio_config *gpio_config);\n#endif\n"
  },
  {
    "path": "kernel/drivers/i2c.h",
    "content": "#ifndef INC_I2C\n#define INC_I2C\n#include \"dma.h\"\n#include \"gpio.h\"\n\n\nstruct i2c_config {\n    int idx;\n    uint32_t base;\n    uint32_t ev_irq;\n    uint32_t er_irq;\n    uint32_t rcc;\n    uint32_t clock_speed;\n    uint32_t fast_mode;\n    uint32_t rise_time;\n    uint32_t bus_clk_frequency;\n    uint32_t clock_f;\n    uint32_t dma_rcc;\n    struct dma_config tx_dma;\n    struct dma_config rx_dma;\n    struct gpio_config pio_scl;\n    struct gpio_config pio_sda;\n};\n\nstruct i2c_slave {\n    int     bus;\n    uint8_t address;\n    void (*isr_tx)(struct i2c_slave *);\n    void (*isr_rx)(struct i2c_slave *);\n    void *priv;\n};\n\nint i2c_create(const struct i2c_config *i2c_config);\nint i2c_init_read(struct i2c_slave *sl, uint8_t reg, uint8_t *buf, uint32_t len);\nint i2c_init_write(struct i2c_slave *sl, uint8_t reg, const uint8_t *buf, uint32_t len);\nint i2c_kthread_read(struct i2c_slave *sl, uint8_t reg, uint8_t *buf, uint32_t len);\nint i2c_kthread_write(struct i2c_slave *sl, uint8_t reg, const uint8_t *buf, uint32_t len);\n\n#endif\n\n"
  },
  {
    "path": "kernel/drivers/ili9341.c",
    "content": "/* Includes ------------------------------------------------------------------*/\n#include <string.h>\n#include \"malloc.h\"\n#include \"framebuffer.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/ltdc.h>\n#include <unicore-mx/stm32/spi.h>\n#include \"gpio.h\"\n#include \"spi.h\"\n\n/* ILI9341 LCD screen ... */\n#define  ILI9341_WIDTH               ((uint16_t)240)  /* LCD PIXEL WIDTH            */\n#define  ILI9341_HEIGHT              ((uint16_t)320)  /* LCD PIXEL HEIGHT           */\n#define  ILI9341_HSYNC               ((uint16_t)10)   /* Horizontal synchronization */\n#define  ILI9341_HBP                 ((uint16_t)20)   /* Horizontal back porch      */\n#define  ILI9341_HFP                 ((uint16_t)10)   /* Horizontal front porch     */\n#define  ILI9341_VSYNC               ((uint16_t)2)   /* Vertical synchronization   */\n#define  ILI9341_VBP                 ((uint16_t)2)    /* Vertical back porch        */\n#define  ILI9341_VFP                 ((uint16_t)4)    /* Vertical front porch       */\n//#define  ILI9341_FREQUENCY_DIVIDER    5               /* LCD Frequency divider      */\n//#define REFRESH_RATE 70 /* Hz */\n\n#define FB_WIDTH    ILI9341_WIDTH\n#define FB_HEIGTH   ILI9341_HEIGHT\n//#define FB_BPP      (16) /* hardcoded RGB565 - 16 bits per pixel */\n#define FB_BPP      (16) /* hardcoded CLUT256 - 8 bit per pixel */\n\n#define SET_WRITE_SINGLE_CMD(x)         (x & (~(0xC0)))\n\n\n/* Private function prototypes -----------------------------------------------*/\nstatic void ltdc_config(void); \nstatic void ltdc_pinmux(void); \nstatic void ltdc_clock(void); \nstatic int ltdc_config_layer(struct fb_info *fb);\n\nstruct dev_ili9341 {\n    struct spi_slave sl; /* First argument, for inheritance */\n    struct device * dev;\n    const struct gpio_config *pio_cs;\n};\n\nstruct ili0341_ctrl_reg\n{\n    uint8_t reg;\n    uint8_t data;\n};\n\nstatic struct dev_ili9341 ILI9341;\n\n\nstatic struct module mod_ltdc = {\n    .family = FAMILY_FILE,\n    .name = \"lcd-controller\",\n};\n\n/* Function to write a register to ILI9341 through SPI  */\nstatic void ili9341_write(uint8_t data)\n{\n    /* set CS low */\n    gpio_clear(ILI9341.pio_cs->base, ILI9341.pio_cs->pin);\n    //spi_xfer(SPI5, SET_WRITE_SINGLE_CMD(reg));\n    spi_xfer(SPI5, data);\n\n    /* set CS high */\n    gpio_set(ILI9341.pio_cs->base, ILI9341.pio_cs->pin);\n}\n\n/* Private functions ---------------------------------------------------------*/\n\nstatic void ltdc_destroy(struct fb_info *fb)\n{\n    // TODO: disable framebuffer\n    \n    if (fb && fb->screen_buffer)\n        f_free((void *)fb->screen_buffer);\n}\n\nstatic int ltdc_config_layer(struct fb_info *fb)\n{\n  uint32_t format = 0; \n\n  /* TODO: move to check / set var */\n  fb->var.xres = FB_WIDTH;\n  fb->var.yres = FB_HEIGTH;\n  fb->var.bits_per_pixel = FB_BPP;\n  //fb->var.pixel_format = FB_PF_RGB565;\n  fb->var.pixel_format = FB_PF_ARGB8888;\n  fb->var.smem_len = fb->var.xres * fb->var.yres * (fb->var.bits_per_pixel/8);\n  fb->var.type = FB_TYPE_PIXELMAP;\n\n  /* Allocate framebuffer memory */\n  fb->screen_buffer = u_malloc(fb->smem_len);\n  if (!fb->screen_buffer)\n  {\n      return -1;\n  }\n  fb->smem_start = fb->screen_buffer;\n\n  /* Windowing configuration */ \n  ltdc_setup_windowing(LTDC_LAYER_2, fb->var.xres, fb->var.xres);\n\n  /* Specifies the pixel format */\n  switch (fb->var.pixel_format)\n  {\n      case FB_PF_RGB565:\n          format = LTDC_LxPFCR_RGB565;\n          break;\n      case FB_PF_ARGB8888:\n          format = LTDC_LxPFCR_ARGB8888;\n          break;\n      case FB_PF_CMAP256:\n          format = LTDC_LxPFCR_L8;\n          break;\n      default:\n          format = LTDC_LxPFCR_RGB565;\n          break;\n  }\n\n  ltdc_set_pixel_format(LTDC_LAYER_2, format);\n\n  /* Default color values */\n  ltdc_set_default_colors(LTDC_LAYER_2, 0, 0, 0, 0);\n\n  /* Constant alpha */\n  ltdc_set_constant_alpha(LTDC_LAYER_2, 255);\n\n  /* Blending factors */\n  ltdc_set_blending_factors(LTDC_LAYER_2, LTDC_LxBFCR_BF1_CONST_ALPHA, LTDC_LxBFCR_BF2_CONST_ALPHA);\n\n  /* Framebuffer memory address */\n  ltdc_set_fbuffer_address(LTDC_LAYER_2, (uint32_t)fb->screen_buffer);\n\n  /* Configures the color frame buffer pitch in byte */\n  ltdc_set_fb_line_length(LTDC_LAYER_2, fb->var.xres * (fb->var.bits_per_pixel/8), fb->var.xres * (fb->var.bits_per_pixel/8));\n\n  /* Configures the frame buffer line number */\n  ltdc_set_fb_line_count(LTDC_LAYER_2, fb->var.yres);\n\n  /* Enable layer 1 */\n  ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_LAYER_ENABLE);\n\n  /* Sets the Reload type */\n  ltdc_reload(LTDC_SRCR_VBR);\n\n  ltdc_ctrl_enable(LTDC_GCR_LTDC_ENABLE);\n\n  return 0;\n}\n\n\n/**\n  * @brief LCD Configuration.\n  * @note  This function Configure tha LTDC peripheral :\n  *        1) Configure the Pixel Clock for the LCD\n  *        2) Configure the LTDC Timing and Polarity\n  *        3) Configure the LTDC Layer 1 :\n  *           - The frame buffer is located at FLASH memory\n  *           - The Layer size configuration : 480x272                      \n  * @retval\n  *  None\n  */\nstatic void ltdc_config(void)\n{ \n  /* LTDC Initialization */\n  ltdc_ctrl_disable(LTDC_GCR_HSPOL_ACTIVE_HIGH); /* Active Low Horizontal Sync */\n  ltdc_ctrl_disable(LTDC_GCR_VSPOL_ACTIVE_HIGH); /* Active Low Vertical Sync */\n  ltdc_ctrl_disable(LTDC_GCR_DEPOL_ACTIVE_HIGH); /* Active Low Date Enable */\n  ltdc_ctrl_disable(LTDC_GCR_PCPOL_ACTIVE_HIGH); /* Active Low Pixel Clock */\n  \n  /* Configure the LTDC */  \n  ltdc_set_tft_sync_timings(ILI9341_HSYNC, ILI9341_VSYNC,\n\t\t\t                ILI9341_HBP,   ILI9341_VBP,\n\t\t\t                ILI9341_WIDTH, ILI9341_HEIGHT,\n\t\t\t                ILI9341_HFP,   ILI9341_VFP);\n  ltdc_ctrl_enable(LTDC_GCR_PCPOL_ACTIVE_HIGH); /* Active Low Pixel Clock */\n\n  ltdc_set_background_color(0, 0, 0);\n//    LTDC_IER = LTDC_IER_RRIE;\n//    nvic_enable_irq(NVIC_LCD_TFT_IRQ);\n\n  //ltdc_ctrl_enable(LTDC_GCR_LTDC_ENABLE);\n}\n\nstatic void ltdc_clock(void)\n{\n\n  /*\n   * The datasheet says (Figure 16, page 151):\n   *     The LCD-TFT clock comes from PLLSAI.\n   *     PLLSRC selects either HSI or HSE.\n   *     PLLSAI's input clock is either HSI or HSE divided by PLLM.\n   *     PLLSAI's PLLLCDCLK output is the input * PLLSAIN / PLLSAIR.\n   *     LCD-TFT clock is PLLLCDCLK divided by PLLSAIDIVR.\n   *\n   * PLLSRC and PLLM are in the RCC_PLLCFGR register.\n   * PLLSAIN and PLLSAIR are in RCC_PLLSAICFGR.\n   * PLLSAIDIVR is in RCC_DCKCFGR;\n   *\n   * In our case,\n   * PLLSRC already selected HSE, which is 8 MHz.\n   * PLLM is already set to 8.  8 MHz / 8 = 1 MHz.\n   * We set PLLSAIN = 192 and PLLSAIR = 4.  1 MHz * 192 / 4 = 48 MHz.\n   * We set PLLSAIDIVR to 8.  48 MHz / 8 = 6 MHz.\n   * So the LCD-TFT pixel clock is 6 MHz.\n   *\n   * The number of clocks per frame is\n   * (VSYNC + VBP + LCD_HEIGHT + VFP) * (HSYNC + HBP + LCD_WIDTH + HFP) =\n   * (2 + 2 + 320 + 4) * (10 + 20 + 240 + 10) = 91840.\n   *\n   * So the refresh frequency is 6 MHz / 91840 ~= 65.6 Hz.\n   */\n  /* Disable PLLSAI */\n  RCC_CR &= ~RCC_CR_PLLSAION;\n  while((RCC_CR & (RCC_CR_PLLSAIRDY))) {};\n\n  uint32_t sain = 192;\n  uint32_t saiq = (RCC_PLLSAICFGR >> RCC_PLLSAICFGR_PLLSAIQ_SHIFT) &\n      RCC_PLLSAICFGR_PLLSAIQ_MASK;\n  uint32_t sair = 4;\n  RCC_PLLSAICFGR = (sain << RCC_PLLSAICFGR_PLLSAIN_SHIFT |\n        saiq << RCC_PLLSAICFGR_PLLSAIQ_SHIFT |\n        sair << RCC_PLLSAICFGR_PLLSAIR_SHIFT);\n  RCC_DCKCFGR |= RCC_DCKCFGR_PLLSAIDIVR_DIVR_8;\n  RCC_CR |= RCC_CR_PLLSAION;\n  while(!(RCC_CR & (RCC_CR_PLLSAIRDY))) {};\n  RCC_APB2ENR |= RCC_APB2ENR_LTDCEN;\n}\n\nstatic int ltdc_blank(struct fb_info *fb)\n{\n    uint32_t pixels = (fb->var.xres * fb->var.yres * (fb->var.bits_per_pixel/8));\n    memset((void *)fb->screen_buffer, 0x0, pixels);\n}\n\nstatic void ltdc_screen_on(void)\n{\n    /* Assert display enable LCD_DISP pin */\n    gpio_set(GPIOF, GPIO10);\n    /* Assert backlight LCD_BL_CTRL pin */\n    //gpio_set(GPIOD, GPIO13);\n}\n\nvoid ltdc_enable_clut(void)\n{\n  /* Disable LTDC color lookup table by setting CLUTEN bit */\n  ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_CLUT_ENABLE);\n\n  /* Sets the Reload type */\n  ltdc_reload(LTDC_SRCR_IMR);\n}\n\n/* Only L8 CLUTs supported for now */\nvoid ltdc_config_clut(uint32_t *CLUT, uint32_t size)\n{\n    uint32_t i = 0;\n\n    for(i = 0; (i < size); i++)\n    {\n        /* Specifies the C-LUT address and RGB value */\n        LTDC_LxCLUTWR(LTDC_LAYER_2) = ((i << 24) | ((uint32_t)(*CLUT) & 0xFF) | ((uint32_t)(*CLUT) & 0xFF00) | ((uint32_t)(*CLUT) & 0xFF0000));\n        CLUT++;\n    }\n}\n\nint ltdc_set_cmap(uint32_t *cmap, struct fb_info *info)\n{\n    //ltdc_config_clut(cmap, 256);\n    //ltdc_enable_clut();\n    return 0;\n}\n\n\nstatic int ltdc_open(struct fb_info *info)\n{\n    /* init LCD */\n}\n\nstatic const struct fb_ops  ltdc_fbops = {  \n                                            .fb_open = ltdc_open,\n                                            .fb_destroy = ltdc_destroy,\n                                            .fb_blank = ltdc_blank,\n                                            .fb_setcmap = ltdc_set_cmap};\n\nstatic struct fb_info ltdc_info = { \n        .fbops = (struct fb_ops *)&ltdc_fbops,\n};\n\n\nstatic void lcd_pinmux(void)\n{\n    int i;\n    struct gpio_config g = { \n            .mode=GPIO_MODE_AF,\n            .speed=GPIO_OSPEED_50MHZ, \n            .optype=GPIO_OTYPE_PP, \n            .pullupdown = GPIO_PUPD_NONE\n    };\n\n    /* Enable the LTDC Clock */\n    rcc_periph_clock_enable(RCC_LTDC);\n\n\n\n\n    /* PA3 */\n    g.base = GPIOA;\n    g.pin = GPIO3;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PA6 */\n    g.base = GPIOA;\n    g.pin = GPIO6;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PA11 */\n    g.base = GPIOA;\n    g.pin = GPIO11;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PA12 */\n    g.base = GPIOA;\n    g.pin = GPIO12;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PB0 */\n    g.base = GPIOB;\n    g.pin = GPIO0;\n    g.af = GPIO_AF9;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PB1 */\n    g.base = GPIOB;\n    g.pin = GPIO1;\n    g.af = GPIO_AF9;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PC7 */\n    g.base = GPIOC;\n    g.pin = GPIO7;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PC10 */\n    g.base = GPIOC;\n    g.pin = GPIO10;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PD3 */\n    g.base = GPIOD;\n    g.pin = GPIO3;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PD6 */\n    g.base = GPIOD;\n    g.pin = GPIO6;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PF10 */\n    g.base = GPIOF;\n    g.pin = GPIO10;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PG6 */\n    g.base = GPIOG;\n    g.pin = GPIO6;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PG10 */\n    g.base = GPIOG;\n    g.pin = GPIO10;\n    g.af = GPIO_AF9;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PG11 */\n    g.base = GPIOG;\n    g.pin = GPIO11;\n    g.af = GPIO_AF11;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PG12 */\n    g.base = GPIOG;\n    g.pin = GPIO12;\n    g.af = GPIO_AF9;\n    gpio_create(&mod_ltdc, &g);\n\n\n    /* PB8:PB11*/\n    for (i = 8; i < 12; i++) {\n        g.base = GPIOB;\n        g.pin = (1 << i);\n        g.af = GPIO_AF14;\n        gpio_create(&mod_ltdc, &g);\n    }\n\n    /* PG7 */\n    g.base = GPIOG;\n    g.pin = GPIO7;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PC6 */\n    g.base = GPIOC;\n    g.pin = GPIO6;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PA4 */\n    g.base = GPIOA;\n    g.pin = GPIO4;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PC2 */\n    g.base = GPIOC;\n    g.pin = GPIO2;\n    g.mode = GPIO_MODE_OUTPUT;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PD12 */\n    g.base = GPIOD;\n    g.pin = GPIO12;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PD11 */\n    g.base = GPIOD;\n    g.pin = GPIO11;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PD13 */\n    g.base = GPIOD;\n    g.pin = GPIO13;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PF7 */\n    g.base = GPIOF;\n    g.pin = GPIO7;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PF9 */\n    g.base = GPIOF;\n    g.pin = GPIO9;\n    gpio_create(&mod_ltdc, &g);\n\n\n    /* LCD_DISP control PC2 (enable) */\n    g.base = GPIOC;\n    g.pin = GPIO2;\n    gpio_create(&mod_ltdc, &g);\n\n    /* LCD_BL control PD13 (output) */\n    g.base = GPIOD;\n    g.pin = GPIO13;\n    gpio_create(&mod_ltdc, &g);\n\n    ltdc_screen_on();\n}\n\n/*\n * void lcd_command(cmd, delay, args, arg_ptr)\n *\n * All singing all dancing 'do a command' feature. Basically it\n * sends a command, and if args are present it sets 'data' and\n * sends those along too.\n */\nstatic void\nlcd_command(uint8_t cmd, int delay, int n_args, const uint8_t *args)\n{\n    //uint32_t timeout;\n    int i, now;\n\n    //gpio_clear(ILI9341.pio_cs->base, ILI9341.pio_cs->pin);\n    //gpio_clear(GPIOC, GPIO2); /* Select the LCD */\n    //rx_pend++;\n    ili9341_write(cmd);\n    /* We need to wait until it is sent, if we turn on the Data\n     * line too soon, it ends up confusing the display to thinking\n     * its a data transfer, as it samples the D/CX line on the last\n     * bit sent.\n     */\n        now = jiffies;\n        //while (now + 10 > jiffies) {};\n\n    //for (timeout = 0; (timeout < 1000) && (rx_pend); timeout++) {\n    //    continue;\n    //}\n    //rx_pend = 0;        /* sometimes, at 10Mhz we miss this */\n    if (n_args) {\n        gpio_set(GPIOD, GPIO13); /* Set the D/CX pin */\n        for (i = 0; i < n_args; i++) {\n            //rx_pend++;\n            ili9341_write(*(args+i));\n        }\n        /* This wait so that we don't pull CS too soon after\n         * sending the last byte of data.\n         */\n        //for (timeout = 0; (timeout < 1000) && (rx_pend); timeout++) {\n        //    continue;\n        //}\n        now = jiffies;\n        //while (now + 10 > jiffies) {};\n\n    }\n    //gpio_set(ILI9341.pio_cs->base, ILI9341.pio_cs->pin);\n    //gpio_set(GPIOC, GPIO2);    /* Turn off chip select */\n    gpio_clear(GPIOD, GPIO13); /* always reset D/CX */\n    if (delay) {\n        now = jiffies;\n        //while (now + 50 > jiffies) {};\n\n        //msleep(delay); /* wait, if called for */\n    }\n}\n\n/* Notes on the less obvious ILI9341 commands: */\n\n/*\n * ILI9341 datasheet, pp 46-49:\n *\n *     RCM[1:0} = 0b10    command 0xb0\n *     DPI[2:0] = 0b110   command 0x3a\n *     RIM      = 0       command 0xf6\n *     PCDIV    = ????    command 0xB6\n *\n * Pp 239-240:\n *     external fosc = DOTCLK / (2 * (PCDIV + 1))\n *\n * (\"Cube\" is how the STM32F4Cube demo software sets the register.\n *  \"Chuck\" is ChuckM's lcd-serial demo, first revision.)\n *\n * Command 0x3A: COLMOD: Pixel Format Set  LCD_PIXEL_FORMAT\n *                Reset              Cube   Chuck\n *      DPI[2:0]   110 (18 bit/pix)   110    101 (16 bit/pix)\n *      DBI[2:0]   110 (18 bit/pix)   110    101 (16 bit/pix)\n *\n * Command 0xB0: RGB Interface Signal      LCD_RGB_INTERFACE\n *                Reset              Cube\n *      Bypass:      0 (direct)        1 (memory)\n *      RCM[1:0]    10                10\n *      VSPL         0 (low)           0\n *      HSPL         0 (low)           0\n *      DPL          0 (rising)        1 (falling)\n *      EPL          1 (low)           0 (high)\n *\n * Command 0xB6: Display Function Control  LCD_DFC\n *                Reset              Cube 0A A7 27 04\n *      PTG[1:0]    10                10\n *      PT[1:0]     10                10\n *      REV          1                 1\n *      GS           0                 0\n *      SS           0 (S1->S720)      1 (S720->S1)\n *      SM           0                 0\n *      ISC[3:0]  0010 (5 frames)   0111 (15 frames)\n *      NL[5:0]   100111          100111\n *      PCDIV[5:0]   ?            000100\n *   S720->S1 moves the origin from the lower left corner to lower right\n *   (viewing the board so the silkscreen is upright)\n *\n * Command 0xF6: Interface Control         LCD_INTERFACE\n *               Reset              Cube  01 00 06\n *      MY_EOR       0                 0\n *      MX_EOR       0                 0\n *      MV_EOR       0                 0\n *      BGR_EOR      0                 0\n *      WEMODE       1 (wrap)          1\n *      EPF[1:0]    00                00\n *      MDT[1:0]    00                00\n *      ENDIAN       0 (MSB first)     0\n *      DM[1:0]     00 (int clk)      01 (RGB ifc)\n *      RM           0 (sys ifc)       1 (RGB ifc)\n *      RIM          0 (1 xfr/pix)     0\n */\n\n/* ILI9341 command definitions */\n\n/* Regulative[sic] Command Set */\n#define ILI_NOP                 0x00\n#define ILI_RESET               0x01\n#define ILI_RD_DID              0x04\n#define ILI_RD_STS              0x09\n#define ILI_RD_PWR_MODE         0x0a\n#define ILI_RD_MADCTL           0x0b\n#define ILI_RD_PXL_FMT          0x0c\n#define ILI_PD_IMG_FMT          0x0d\n#define ILI_RD_SIG_MODE         0x0e\n#define ILI_RD_DIAG_RSLT        0x0f\n#define ILI_ENTER_SLEEP         0x10\n#define ILI_SLEEP_OUT           0x11\n#define ILI_PARTIAL_ON          0x12\n#define ILI_NORMAL_MODE_ON      0x13\n#define ILI_INVERSE_ON          0x20\n#define ILI_INVERSE_OFF         0x21\n#define ILI_GAMMA_SET           0x26\n#define ILI_DISP_OFF            0x28\n#define ILI_DISP_ON             0x29\n#define ILI_CAS                 0x2a\n#define ILI_PAS                 0x2b\n#define ILI_MEM_WRITE           0x2c\n#define ILI_COLOR_SET           0x2d\n#define ILI_MEM_READ            0x2e\n#define ILI_PARTIAL_AREA        0x30\n#define ILI_VERT_SCROLL_DEF     0x33\n#define ILI_TEAR_EFF_OFF        0x34\n#define ILI_TEAR_EFF_ON         0x35\n#define ILI_MEM_ACC_CTL         0x36\n#define ILI_V_SCROLL_START      0x37\n#define ILI_IDLE_OFF            0x38\n#define ILI_IDLE_ON             0x39\n#define ILI_PIX_FMT_SET         0x3a\n#define ILI_WR_MEM_CONT         0x3c\n#define ILI_RD_MEM_CONT         0x3e\n#define ILI_SET_TEAR_LINE       0x44\n#define ILI_GET_SCANLINE        0x45\n#define ILI_WR_BRIGHTNESS       0x51\n#define ILI_RD_BRIGHTNESS       0x52\n#define ILI_WR_CTRL             0x53\n#define ILI_RD_CTRL             0x54\n#define ILI_WR_CABC             0x55\n#define ILI_RD_CABC             0x56\n#define ILI_WR_CABC_MIN         0x5e\n#define ILI_RD_CABC_MAX         0x5f\n#define ILI_RD_ID1              0xda\n#define ILI_RD_ID2              0xdb\n#define ILI_RD_ID3              0xdc\n\n/* Extended Command Set */\n#define ILI_RGB_IFC_CTL         0xb0\n#define ILI_FRM_CTL_NORM        0xb1\n#define ILI_FRM_CTL_IDLE        0xb2\n#define ILI_FRM_CTL_PART        0xb3\n#define ILI_INVERSE_CTL         0xb4\n#define ILI_PORCH_CTL           0xb5\n#define ILI_FUNC_CTL            0xb6\n#define ILI_ENTRY_MODE_SET      0xb7\n#define ILI_BL_CTL_1            0xb8\n#define ILI_BL_CTL_2            0xb9\n#define ILI_BL_CTL_3            0xba\n#define ILI_BL_CTL_4            0xbb\n#define ILI_BL_CTL_5            0xbc\n#define ILI_BL_CTL_7            0xbe\n#define ILI_BL_CTL_8            0xbf\n#define ILI_PWR_CTL_1           0xc0\n#define ILI_PWR_CTL_2           0xc1\n#define ILI_VCOM_CTL_1          0xc5\n#define ILI_VCOM_CTL_2          0xc7\n#define ILI_NV_MEM_WR           0xd0\n#define ILI_NV_MEM_PROT_KEY     0xd1\n#define ILI_NV_MEM_STATUS_RD    0xd2\n#define ILI_RD_ID4              0xd3\n#define ILI_POS_GAMMA           0xe0\n#define ILI_NEG_GAMMA           0xe1\n#define ILI_GAMMA_CTL_1         0xe2\n#define ILI_GAMMA_CTL_2         0xe3\n#define ILI_IFC_CTL             0xf6\n\n/*\n * This structure defines the sequence of commands to send\n * to the Display in order to initialize it. The AdaFruit\n * folks do something similar, it helps when debugging the\n * initialization sequence for the display.\n */\n\n#define MAX_INLINE_ARGS (sizeof(uint8_t *))\nstruct tft_command {\n  uint16_t delay;   /* If you need a delay after */\n  uint8_t cmd;    /* command to send */\n  uint8_t n_args;   /* How many arguments it has */\n  union {\n    uint8_t args[MAX_INLINE_ARGS]; /* The first four arguments */\n    const uint8_t *aptr; /* More than four arguemnts */\n  };\n};\n\nstatic const uint8_t pos_gamma_args[] = { 0x0F, 0x29, 0x24, 0x0C, 0x0E,\n            0x09, 0x4E, 0x78, 0x3C, 0x09,\n            0x13, 0x05, 0x17, 0x11, 0x00 };\nstatic const uint8_t neg_gamma_args[] = { 0x00, 0x16, 0x1B, 0x04, 0x11,\n            0x07, 0x31, 0x33, 0x42, 0x05,\n            0x0C, 0x0A, 0x28, 0x2F, 0x0F };\n\n/*\n * These are the commands we're going to send to the\n * display to initialize it. We send them all, in sequence\n * with occasional delays. Commands that require data bytes\n * as arguments, indicate how many bytes to pull out the\n * above array to include.\n *\n * The sequence was pieced together from the ST Micro demo\n * code, the data sheet, and other sources on the web.\n */\nconst struct tft_command initialization[] = {\n  {  0, ILI_PWR_CTL_1,        1, .args = { 0x10 } },\n  {  0, ILI_PWR_CTL_2,        1, .args = { 0x10 } },\n  {  0, ILI_VCOM_CTL_1,       2, .args = { 0x45, 0x15 } },\n  {  0, ILI_VCOM_CTL_2,       1, .args = { 0x90 } },\n  {  0, ILI_MEM_ACC_CTL,      1, .args = { 0x08 } },\n  {  0, ILI_RGB_IFC_CTL,      1, .args = { 0xc0 } },\n  {  0, ILI_IFC_CTL,          3, .args = { 0x01, 0x00, 0x06 } },\n  {  0, ILI_GAMMA_SET,        1, .args = { 0x01 } },\n  {  0, ILI_POS_GAMMA,       15, .aptr = pos_gamma_args },\n  {  0, ILI_NEG_GAMMA,       15, .aptr = neg_gamma_args },\n  { +5, ILI_SLEEP_OUT,        0, .args = {} },\n  {  0, ILI_DISP_ON,          0, .args = {} },\n};\n\nstatic void\ninitialize_display(const struct tft_command cmds[], size_t cmd_count)\n{\n  size_t i;\n\n  for (i = 0; i < cmd_count; i++) {\n    uint8_t arg_count = cmds[i].n_args;\n    const uint8_t *args = cmds[i].args;\n    if (arg_count > MAX_INLINE_ARGS) {\n      args = cmds[i].aptr;\n    }\n    lcd_command(cmds[i].cmd, cmds[i].delay, arg_count, args);\n  }\n}\n\nstruct gpio_config ili9341_pio = {\n    .base=GPIOC,\n    .pin=GPIO2,\n    .mode=GPIO_MODE_OUTPUT,\n    .pullupdown=GPIO_PUPD_PULLUP\n};\n\n\nstatic void ili9341_init(void)\n{\n    memset(&ILI9341, 0, sizeof(struct dev_ili9341));\n\n   /* Populate spi_slave struct */\n    ILI9341.sl.bus = 5;\n    //ILI9341.sl.isr = ili9341_isr;\n    ILI9341.pio_cs = &ili9341_pio;\n    gpio_create(&mod_ltdc, &ili9341_pio);\n    gpio_set(ILI9341.pio_cs->base, ILI9341.pio_cs->pin);\n \n    /* Set up the display */\n    initialize_display(initialization,\n         sizeof(initialization) / sizeof(initialization[0]));\n}\n\n\n/* DRIVER INIT */\nvoid ltdc_init(void)\n{\n    lcd_pinmux();\n    ltdc_clock(); \n    ltdc_config(); /* Configure LCD : Only one layer is used */\n    ltdc_config_layer(&ltdc_info);\n    ili9341_init();\n    register_framebuffer(&ltdc_info);\n    register_module(&mod_ltdc);\n}\n"
  },
  {
    "path": "kernel/drivers/l3gd20.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"ioctl.h\"\n#include \"l3gd20.h\"\n#include \"gpio.h\"\n#include \"exti.h\"\n#include <unicore-mx/stm32/f4/exti.h>\n#include \"stm32f4_dma.h\"\n#include \"stm32f4_spi.h\"\n\ntypedef enum\n{\n    L3GD20_IDLE,\n    L3GD20_READ,\n    L3GD20_WRITE,\n    L3GD20_PENDING,\n    L3GD20_READING\n}L3GD20_MODE;\n\nstruct dev_l3gd20 {\n    struct device * dev;\n    struct fnode *spi_fnode;\n    struct fnode *cs_fnode;\n    struct fnode *int_1_fnode;\n    struct fnode *int_2_fnode;\n    L3GD20_MODE mode;\n};\n\nstruct l3gd20_ctrl_reg\n{\n    uint8_t reg;\n    uint8_t data;\n};\n\n\n#define MAX_L3GD20S 1\n\nstatic struct dev_l3gd20 dev_l3gd20 = { };\n\n\nstatic int devl3gd20_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int devl3gd20_ioctl(struct fnode * fno, const uint32_t cmd, void *arg);\nstatic int devl3gd20_close(struct fnode *fno);\n\nstatic struct module mod_devl3gd20 = {\n    .family = FAMILY_FILE,\n    .name = \"l3gd20\",\n    .ops.open = device_open,\n    .ops.read = devl3gd20_read,\n    .ops.ioctl = devl3gd20_ioctl,\n    .ops.close = devl3gd20_close,\n};\n\nstatic void completion(void * arg)\n{\n    dev_l3gd20.cs_fnode->owner->ops.write(dev_l3gd20.cs_fnode, \"1\", 1);\n\n    if (dev_l3gd20.dev->task != NULL)\n        task_resume(dev_l3gd20.dev->task);\n}\n\nstatic void int1_callback(void *arg)\n{\n    (void)arg;\n}\n\n\nstatic void int2_callback(void *arg)\n{\n    (void)arg;\n    dev_l3gd20.cs_fnode->owner->ops.write(dev_l3gd20.cs_fnode, \"1\", 1);\n\n    if (dev_l3gd20.dev->task != NULL)\n        task_resume(dev_l3gd20.dev->task);\n}\n\n\nstatic int devl3gd20_ioctl(struct fnode * fno, const uint32_t cmd, void *arg)\n{\n    struct dev_l3gd20 *l3gd20 = FNO_MOD_PRIV(fno, &mod_devl3gd20);\n    struct l3gd20_ctrl_reg * ctrl = (struct l3gd20_ctrl_reg *) arg;\n    static uint8_t ioctl_ibuffer[2];\n    static uint8_t ioctl_obuffer[2];\n\n    if (!l3gd20)\n        return -1;\n\n    if(l3gd20->mode == L3GD20_IDLE)\n    {\n        ioctl_obuffer[0] = ctrl->reg;\n\n        if(cmd == IOCTL_L3GD20_READ_CTRL_REG)\n        {\n            ioctl_obuffer[0] |= 0x80;\n            ioctl_obuffer[1] = 0;\n            l3gd20->mode = L3GD20_READ;\n        }\n        else\n        {\n            ioctl_obuffer[1] = ctrl->data;\n            l3gd20->mode = L3GD20_WRITE;\n        }\n\n        l3gd20->dev->task = this_task();\n        task_suspend();\n\n        l3gd20->cs_fnode->owner->ops.write(l3gd20->cs_fnode, \"0\", 1);\n        devspi_xfer(l3gd20->spi_fnode, completion, l3gd20,  ioctl_obuffer, ioctl_ibuffer, 2);\n\n        return SYS_CALL_AGAIN;\n    }\n\n    if(l3gd20->mode == L3GD20_READ)\n    {\n        ctrl->data = ioctl_ibuffer[1];\n    }\n    l3gd20->mode = L3GD20_IDLE;\n\n    return 0;\n}\n\nstatic int devl3gd20_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    const struct dev_spi *spi;\n    struct dev_l3gd20 *l3gd20 = FNO_MOD_PRIV(fno, &mod_devl3gd20);\n\n    static uint8_t rd_ibuffer[7];\n    static uint8_t rd_obuffer[7];\n\n    if (len <= 0)\n        return len;\n\n    if (!l3gd20)\n        return -1;\n\n    /* First read is a fake just to get the DRDY IRQ going - what a bloody awful gyro*/\n    if(l3gd20->mode == L3GD20_IDLE)\n    {\n        exti_enable(1, 1);\n\n        l3gd20->mode = L3GD20_PENDING;\n        rd_obuffer[0] = 0xE8;\n\n        l3gd20->dev->task = this_task();\n        task_suspend();\n\n        l3gd20->cs_fnode->owner->ops.write(l3gd20->cs_fnode, \"0\", 1);\n        devspi_xfer(l3gd20->spi_fnode, completion, l3gd20,  rd_obuffer, rd_ibuffer, 7);\n        return SYS_CALL_AGAIN;\n    }\n    else if(l3gd20->mode == L3GD20_PENDING)\n    {\n        l3gd20->mode = L3GD20_READING;\n        rd_obuffer[0] = 0xE8;\n\n        l3gd20->dev->task = this_task();\n        task_suspend();\n\n        l3gd20->cs_fnode->owner->ops.write(l3gd20->cs_fnode, \"0\", 1);\n        devspi_xfer(l3gd20->spi_fnode, completion, l3gd20,  rd_obuffer, rd_ibuffer, 7);\n        return SYS_CALL_AGAIN;\n    }\n    else if(l3gd20->mode == L3GD20_READING)\n    {\n        if(len > 6)\n            len = 6;\n        exti_enable(1, 0);\n        memcpy(buf, &rd_ibuffer[1], len);\n        l3gd20->mode = L3GD20_PENDING;\n    }\n    return len;\n}\n\nstatic int devl3gd20_close(struct fnode *fno)\n{\n    struct dev_l3gd20 *l3gd20;\n    l3gd20 = FNO_MOD_PRIV(fno, &mod_devl3gd20);\n    if (!l3gd20)\n        return -1;\n    l3gd20->mode = L3GD20_IDLE;\n\n    exti_enable(1, 0);\n    return 0;\n}\n\nstatic void l3gd20_fno_init(struct fnode *dev, uint32_t n, const struct l3gd20_addr * addr)\n{\n    struct dev_l3gd20 *l = &dev_l3gd20;\n\n    l->dev = device_fno_init(&mod_devl3gd20, \"/dev/gyro\", dev, FL_RDWR, l);\n    l->spi_fnode = fno_search(addr->spi_name);\n    l->cs_fnode = fno_search(addr->spi_cs_name);\n    l->cs_fnode->owner->ops.write(l->cs_fnode, \"1\", 1);\n    l->mode = L3GD20_IDLE;\n}\n\n\nvoid l3gd20_init(struct fnode * dev, const struct l3gd20_addr l3gd20_addr)\n{\n    int i = 0;\n    l3gd20_fno_init(dev, i, &l3gd20_addr);\n    exti_register(l3gd20_addr.pio1_base, l3gd20_addr.pio1_pin, EXTI_TRIGGER_RISING, int1_callback, NULL);\n    exti_register(l3gd20_addr.pio2_base, l3gd20_addr.pio2_pin, EXTI_TRIGGER_RISING, int2_callback, NULL);\n    register_module(&mod_devl3gd20);\n}\n"
  },
  {
    "path": "kernel/drivers/l3gd20.h",
    "content": "#ifndef INC_L3GD20\n#define INC_L3GD20\n\nstruct l3gd20_addr {\n    const char * name;\n    const char * spi_name;\n    const char * spi_cs_name;\n    uint32_t pio1_base;\n    uint32_t pio1_pin;\n    uint32_t pio2_base;\n    uint32_t pio2_pin;\n\n};\n\nvoid l3gd20_init(struct fnode *dev, const struct l3gd20_addr l3gd20_addr);\n\n#endif\n\n"
  },
  {
    "path": "kernel/drivers/lis3dsh.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"ioctl.h\"\n#include \"gpio.h\"\n#include \"exti.h\"\n#include \"dma.h\"\n#include \"spi.h\"\n#include <unicore-mx/stm32/spi.h>\n\n/* LIS3DSH registers addresses */\n#define ADD_REG_WHO_AM_I\t\t\t\t0x0F\n#define ADD_REG_CTRL_4\t\t\t\t\t0x20\n#define ADD_REG_OUT_X_L\t\t\t\t\t0x28\n#define ADD_REG_OUT_X_H\t\t\t\t\t0x29\n#define ADD_REG_OUT_Y_L\t\t\t\t\t0x2A\n#define ADD_REG_OUT_Y_H\t\t\t\t\t0x2B\n#define ADD_REG_OUT_Z_L\t\t\t\t\t0x2C\n#define ADD_REG_OUT_Z_H\t\t\t\t\t0x2D\n\n/* WHO AM I register default value */\n#define UC_WHO_AM_I_DEFAULT_VALUE\t\t0x3F\n\n/* ADD_REG_CTRL_4 register configuration value:\n * X,Y,Z axis enabled and 400Hz of output data rate */\n\n#define UC_ADD_REG_CTRL_4_CFG_OFF               0x00\n#define UC_ADD_REG_CTRL_4_CFG_3_125HZ           ((0x10) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_6_25HZ            ((0x20) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_12_5HZ            ((0x30) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_25HZ              ((0x40) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_50HZ              ((0x50) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_3_100HZ           ((0x60) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_3_400HZ           ((0x70) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_3_800HZ           ((0x80) | (0x07))\n#define UC_ADD_REG_CTRL_4_CFG_3_1600HZ          ((0x90) | (0x07))\n\n#define UC_ADD_REG_CTRL_4_CFG_VALUE_DEFAULT\t\tUC_ADD_REG_CTRL_4_CFG_25HZ\n\n\n/* Sensitivity for 2G range [mg/digit] */\n#define SENS_2G_RANGE_MG_PER_DIGIT\t\t((float)0.06)\n\n/* LED threshold value in mg */\n#define LED_TH_MG\t\t\t\t(1000)\t/* 1000mg (1G) */\n\n/* set read single command. Attention: command must be 0x3F at most */\n#define SET_READ_SINGLE_CMD(x)\t\t\t(x | 0x80)\n/* set read multiple command. Attention: command must be 0x3F at most */\n#define SET_READ_MULTI_CMD(x)\t\t\t(x | 0xC0)\n/* set write single command. Attention: command must be 0x3F at most */\n#define SET_WRITE_SINGLE_CMD(x)\t\t\t(x & (~(0xC0)))\n/* set write multiple command. Attention: command must be 0x3F at most */\n#define SET_WRITE_MULTI_CMD(x)\t\t\t(x & (~(0x80))\t\\\n\t\t\t\t\t\t x |= 0x40)\n\nstruct dev_lis3dsh {\n    struct spi_slave sl; /* First argument, for inheritance */\n    struct device * dev;\n    const struct gpio_config *pio_cs;\n};\n\nstruct lis3dsh_ctrl_reg\n{\n    uint8_t reg;\n    uint8_t data;\n};\n\nstatic struct dev_lis3dsh LIS3DSH;\n\nstatic int devlis3dsh_open(const char *path, int flags);\nstatic int devlis3dsh_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int devlis3dsh_close(struct fnode *fno);\n\nstatic struct module mod_devlis3dsh = {\n    .family = FAMILY_FILE,\n    .name = \"lis3dsh\",\n    .ops.open = devlis3dsh_open,\n    .ops.read = devlis3dsh_read,\n    .ops.close = devlis3dsh_close,\n};\n\n\n/* Function to write a register to LIS3DSH through SPI  */\nstatic void lis3dsh_write_reg(int reg, int data)\n{\n\t/* set CS low */\n    gpio_clear(LIS3DSH.pio_cs->base, LIS3DSH.pio_cs->pin);\n\tspi_xfer(SPI1, SET_WRITE_SINGLE_CMD(reg));\n\tspi_xfer(SPI1, data);\n\t/* set CS high */\n    gpio_set(LIS3DSH.pio_cs->base, LIS3DSH.pio_cs->pin);\n}\n\n\n/* Function to read a register from LIS3DSH through SPI */\nstatic int lis3dsh_read_reg(int reg)\n{\n\tint reg_value;\n\t/* set CS low */\n    gpio_clear(LIS3DSH.pio_cs->base, LIS3DSH.pio_cs->pin);\n\treg_value = spi_xfer(SPI1, SET_READ_SINGLE_CMD(reg));\n\treg_value = spi_xfer(SPI1, 0xFF);\n\t/* set CS high */\n    gpio_set(LIS3DSH.pio_cs->base, LIS3DSH.pio_cs->pin);\n\treturn reg_value;\n}\n\nstatic int devlis3dsh_open(const char *path, int flags)\n{\n    struct fnode *f = fno_search(path);\n    volatile int int_reg_value;\n    if (!f)\n        return -1;\n    /* get WHO AM I value */\n    int_reg_value = lis3dsh_read_reg(ADD_REG_WHO_AM_I);\n\n    /* if WHO AM I value is the expected one */\n    if (int_reg_value == UC_WHO_AM_I_DEFAULT_VALUE) {\n        /* set output data rate to 400 Hz and enable X,Y,Z axis */\n        lis3dsh_write_reg(ADD_REG_CTRL_4, UC_ADD_REG_CTRL_4_CFG_VALUE_DEFAULT);\n        /* verify written value */\n        int_reg_value = lis3dsh_read_reg(ADD_REG_CTRL_4);\n        /* if written value is different */\n        if (int_reg_value != UC_ADD_REG_CTRL_4_CFG_VALUE_DEFAULT) {\n            return -EIO;\n        }\n    } else {\n        return -EIO;\n    }\n    return task_filedesc_add(f);\n}\n\nstatic int devlis3dsh_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct dev_lis3dsh *lis3dsh = FNO_MOD_PRIV(fno, &mod_devlis3dsh);\n    uint8_t reg_base = ADD_REG_OUT_X_L;\n    uint8_t i;\n    volatile int int_reg_value;\n    if (len < 6)\n        return len;\n\n    if (!lis3dsh)\n        return -1;\n    for (i = 0; i < 6; i++) {\n        ((uint8_t*)buf)[i] = lis3dsh_read_reg(reg_base + i);\n    }\n    return 6;\n}\n\nstatic int devlis3dsh_close(struct fnode *fno)\n{\n    struct dev_lis3dsh *lis3dsh;\n    lis3dsh = FNO_MOD_PRIV(fno, &mod_devlis3dsh);\n    if (!lis3dsh)\n        return -1;\n\n    return 0;\n}\n\nstatic void lis3dsh_isr(struct spi_slave *sl)\n{\n    struct dev_lis3dsh *lis = (struct dev_lis3dsh *)sl;\n    task_resume(lis->dev->task);\n}\n\n\nint lis3dsh_init(uint8_t bus, const struct gpio_config *lis3dsh_cs)\n{\n    struct fnode *devfs;\n    memset(&LIS3DSH, 0, sizeof(struct dev_lis3dsh));\n\n    devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return -EFAULT;\n\n    LIS3DSH.dev = device_fno_init(&mod_devlis3dsh, \"ins\", devfs, FL_RDONLY, &LIS3DSH);\n    if (!LIS3DSH.dev)\n        return -EFAULT;\n\n    /* Populate spi_slave struct */\n    LIS3DSH.sl.bus = bus;\n    LIS3DSH.sl.isr = lis3dsh_isr;\n    LIS3DSH.pio_cs = lis3dsh_cs;\n    register_module(&mod_devlis3dsh);\n    gpio_create(&mod_devlis3dsh, lis3dsh_cs);\n    gpio_set(LIS3DSH.pio_cs->base, LIS3DSH.pio_cs->pin);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/lis3dsh.h",
    "content": "#ifndef LIS3DSH_INC\n#define LIS3DSH_INC\n#   ifdef CONFIG_DEVLIS3DSH\n        int lis3dsh_init(uint8_t bus, const struct gpio_config *lis3dsh_cs);\n#   else\n#       define lis3dsh_init(...) (0)\n#   endif\n#endif\n"
  },
  {
    "path": "kernel/drivers/lm3s_eth.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Maxime Vincent\n *\n */\n \n#include <stdint.h>\n#include \"frosted.h\"\n#include \"gpio.h\"\n#include \"eth.h\"\n\n#include <pico_stack.h>\n#include <pico_device.h>\n#include <unicore-mx/ethernet/mac.h>\n#include <unicore-mx/ethernet/phy.h>\n#include \"unicore-mx/cm3/nvic.h\"\n\n#define dbg(...)\n\n#define ETH_MAX_FRAME    (1524)                 /* Round to multiple of 4 bytes! */\n#define ETH_IRQ_PRIO        (1)\n#define ETH_IRQMASK_RX (1)                      /* Interrupt Mask for RXINT (bit 0) */\n\n/* FIXME: Put in board config */\n#define BOARD_PHY_RMII                          /* Whether the board uses RMII or MII */\n#define BOARD_phy_addr      PHY_LAN8710A_ID     /* The PHY ID to be detected on one of the PHY addresses */\n\n/* Some known PHY-identifiers */\n#define PHY_KSZ8021_ID    0x00221556\n#define PHY_KS8721_ID     0x00221610\n#define PHY_DP83848I_ID   0x20005C90\n#define PHY_LAN8710A_ID   0x0007C0F1\n#define PHY_DM9161_ID     0x0181B8A0\n#define PHY_AM79C875_ID   0x00225540\n#define PHY_STE101P_ID    0x00061C50\n\nstruct dev_eth {\n    struct pico_device dev;\n    uint32_t rx_prod;\n    uint32_t rx_cons;\n    uint8_t mac_addr[6];\n    uint8_t phy_addr;\n};\n\nstatic struct module mod_eth = {\n    .family = FAMILY_DEV,\n    .name = \"ethernet\",\n};\n\nstatic struct dev_eth * dev_eth = NULL;\nstatic const uint8_t default_mac[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};\n\nstatic uint8_t temp_rx_buf[ETH_MAX_FRAME];\n\nstatic int eth_poll(struct pico_device *dev, int loop_score)\n{\n    uint32_t rx_len = 0;\n    while (eth_rx(temp_rx_buf, &rx_len, ETH_MAX_FRAME) && (loop_score > 0))\n    {\n        pico_stack_recv(dev, temp_rx_buf, rx_len);\n        rx_len = 0;\n        loop_score--;\n    }\n    return loop_score;\n}\n\nstatic int eth_send(struct pico_device *dev, void * buf, int len)\n{\n    if (eth_tx(buf, len))\n        return len;\n    else\n        return 0;\n}\n\nint pico_eth_start(void)\n{\n    const char ipstr[] = CONFIG_ETH_DEFAULT_IP;\n    const char nmstr[] = CONFIG_ETH_DEFAULT_NM;\n    const char gwstr[] = CONFIG_ETH_DEFAULT_GW;\n    struct pico_ip4 default_ip, default_nm, default_gw, zero;\n\n    zero.addr = 0U;\n    pico_string_to_ipv4(ipstr, &default_ip.addr);\n    pico_string_to_ipv4(nmstr, &default_nm.addr);\n    pico_string_to_ipv4(gwstr, &default_gw.addr);\n    \n\n    dev_eth = kalloc(sizeof(struct dev_eth));\n    if (!dev_eth)\n        return -1;\n    memset(dev_eth, 0, sizeof(struct dev_eth));\n\n    /* set pico function pointers */\n    dev_eth->dev.poll = eth_poll;\n    dev_eth->dev.send = eth_send;\n\n    if (pico_device_init(&dev_eth->dev,\"eth0\", default_mac) < 0) {\n        kfree(dev_eth);\n        return -1;\n    }\n    /* Set address/netmask */\n    pico_ipv4_link_add(&dev_eth->dev, default_ip, default_nm);\n    /* Set default gateway */\n    if (default_gw.addr)\n        pico_ipv4_route_add(zero, zero, default_gw, 1, NULL);\n\n    /* Enabling required interrupt sources.*/\n\n    eth_start();\n    return 0;\n\n}\n\nvoid eth_isr(void)\n{\n    eth_irq_ack_pending(ETH_IRQMASK_RX);\n    frosted_tcpip_wakeup();\n}\n\n/* HW initialization */\nint ethernet_init(const struct eth_config *conf)\n{\n    (void)conf;\n    eth_init(0, ETH_CLK_50MHZ); /* does a phy_reset */\n    nvic_enable_irq(NVIC_ETH_IRQ);\n    eth_irq_enable(ETH_IRQMASK_RX);\n    eth_set_mac((uint8_t*)default_mac);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/lsm303dlhc.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"ioctl.h\"\n#include \"lsm303dlhc.h\"\n#include \"gpio.h\"\n#include \"exti.h\"\n#include \"dma.h\"\n#include \"i2c.h\"\n\n#define LSM303_I2C_INS_ADDR     0x30\n#define LSM303_I2C_COMPASS_ADDR 0x3C\n\n\nenum lsm303_state {\n    LSM303_STATE_DISABLED = 0,\n    LSM303_STATE_IDLE,\n    LSM303_STATE_BUSY,\n    LSM303_STATE_RX_RDY\n};\n\nstruct dev_lsm303dlhc {\n    struct i2c_slave i2c; /* As first argument, so isr callbacks will use this as arg */\n    struct device * dev;\n    enum lsm303_state state;\n    union dev_lsm303dlhc_data {\n        uint8_t data[6];\n        struct __attribute__((packed)) ins_data_xyz {\n            int16_t x;\n            int16_t y;\n            int16_t z;\n        } xyz;\n    } ins_data;\n} INS;\n\nstatic int devlsm303dlhc_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int devlsm303dlhc_close(struct fnode *fno);\n\nstatic struct module mod_devlsm303dlhc = {\n    .family = FAMILY_FILE,\n    .name = \"lsm303dlhc\",\n    .ops.open = device_open,\n    .ops.read = devlsm303dlhc_read,\n    .ops.close = devlsm303dlhc_close,\n};\n\n\n/* I2C operation callbacks, executed in IRQ context, and with I2C mutex held. */\nstatic void isr_tx(struct i2c_slave * arg)\n{\n    struct dev_lsm303dlhc *lsm303dlhc = (struct dev_lsm303dlhc *) arg;\n    switch (lsm303dlhc->state) {\n        case LSM303_STATE_DISABLED:\n            lsm303dlhc->state = LSM303_STATE_IDLE;\n            task_resume(lsm303dlhc->dev->task);\n            break;\n        case LSM303_STATE_IDLE:\n            lsm303dlhc->state = LSM303_STATE_DISABLED;\n            break;\n    }\n}\n\nstatic void isr_rx(struct i2c_slave * arg)\n{\n    struct dev_lsm303dlhc *lsm303dlhc = (struct dev_lsm303dlhc *) arg;\n    lsm303dlhc->state = LSM303_STATE_RX_RDY;\n    if (lsm303dlhc->dev->task != NULL)\n        task_resume(lsm303dlhc->dev->task);\n}\n\n\nstatic void int1_callback(void *arg)\n{\n    (void*)arg;\n}\n\nstatic void int2_callback(void *arg)\n{\n    (void*)arg;\n}\n\nstatic void drdy_callback(void *arg)\n{\n    (void*)arg;\n}\n\n\n#define CTRL_REG1_A (0x20)\n#define OUT_X_L_A   (0x28)\n\nstatic int devlsm303dlhc_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct dev_lsm303dlhc *lsm303dlhc = FNO_MOD_PRIV(fno, &mod_devlsm303dlhc);\n    uint8_t val;\n\n    if (!lsm303dlhc)\n        return -EINVAL;\n    if (len == 0)\n        return -EINVAL;\n\n    switch (lsm303dlhc->state) {\n        case LSM303_STATE_DISABLED:\n            lsm303dlhc->dev->task = this_task();\n            val = 0x27; /* PM=001, DR=00, XYZ=111 */\n            i2c_init_write(&lsm303dlhc->i2c, CTRL_REG1_A, &val, 1);\n            task_suspend();\n            return SYS_CALL_AGAIN;\n        case LSM303_STATE_IDLE:\n            lsm303dlhc->dev->task = this_task();\n            i2c_init_write(&lsm303dlhc->i2c, OUT_X_L_A, lsm303dlhc->ins_data.data, 6);\n            task_suspend();\n            return SYS_CALL_AGAIN;\n\n        case LSM303_STATE_RX_RDY:\n            if (len > 6)\n                len = 6;\n            memcpy(buf, lsm303dlhc->ins_data.data, len);\n            lsm303dlhc->state = LSM303_STATE_IDLE;\n            val = 0x07; /* PM=000, DR=00, XYZ=111 */\n            i2c_init_write(&lsm303dlhc->i2c, CTRL_REG1_A, &val, 1);\n            return len;\n    }\n}\n\nstatic int devlsm303dlhc_close(struct fnode *fno)\n{\n    struct dev_lsm303dlhc *lsm303dlhc = FNO_MOD_PRIV(fno, &mod_devlsm303dlhc);\n    uint8_t val = 0x07; /* PM=000, DR=00, XYZ=111 */\n    lsm303dlhc->state = LSM303_STATE_IDLE;\n    i2c_init_write(&lsm303dlhc->i2c, CTRL_REG1_A, &val, 1);\n    return 0;\n}\n\nint lsm303dlhc_init(int bus)\n{\n    struct fnode *devfs;\n    memset(&INS, 0, sizeof(struct dev_lsm303dlhc));\n\n    devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return -EFAULT;\n\n    INS.dev = device_fno_init(&mod_devlsm303dlhc, \"ins\", devfs, FL_RDONLY, &INS);\n    if (!INS.dev)\n        return -EFAULT;\n\n    /* Populate i2c_slave struct */\n    INS.i2c.bus = bus;\n    INS.i2c.address = LSM303_I2C_INS_ADDR;\n    INS.i2c.isr_tx = isr_tx;\n    INS.i2c.isr_rx = isr_rx;\n\n    register_module(&mod_devlsm303dlhc);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/lsm303dlhc.h",
    "content": "#ifndef INC_LSM303DLHC\n#define INC_LSM303DLHC\n\nstruct lsm303dlhc_addr {\n    const char * name;\n    const char * i2c_name;\n    uint32_t pio1_base;\n    uint32_t pio2_base;\n    uint32_t drdy_base;\n    uint32_t pio1_pin;\n    uint32_t pio2_pin;\n    uint32_t drdy_pin;\n    uint8_t address;\n    uint8_t drdy_address;\n};\n\nint lsm303dlhc_init(int bus);\n\n#endif\n\n"
  },
  {
    "path": "kernel/drivers/ltdc.h",
    "content": "#ifndef INC_LTDC\n#define INC_LTDC\n\n#ifdef CONFIG_LTDC\nint ltdc_init(void);\n#else\n#  define ltdc_init() ((-ENOENT))\n#endif\n#endif\n"
  },
  {
    "path": "kernel/drivers/mccog21.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera <root@danielinux.net>\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"cirbuf.h\"\n#include \"dma.h\"\n#include \"cirbuf.h\"\n#include \"i2c.h\"\n\n#define MCCOG21_I2C_ADDR (0x7c)\n\n#define MCC0G21_CLEAR_DISPLAY (0x01)\n#define MCC0G21_RETURN_HOME   (0x01)\n#define MCC0G21_ENTRY_MODE    (0x04)\n#   define MCC0G21_ENTRY_MODE_INCREMENT   (0x02)\n#   define MCC0G21_ENTRY_MODE_DECREMENT   (0x00)\n#   define MCC0G21_ENTRY_SHIFT_ON         (0x01)\n#   define MCC0G21_ENTRY_SHIFT_OFF        (0x00)\n#define MCC0G21_ONOFF         (0x08)\n#   define MCC0G21_DISPLAY_ON       (1 << 2)\n#   define MCC0G21_CURSOR_ON        (1 << 1)\n#   define MCC0G21_CURSOR_BLINK     (1 << 0)\n\n#define MCC0G21_SHIFT         (0x10)\n\n#define MCC0G21_OSC_FREQ (0x10)\n#   define MCC0G21_OSC_FREQ_192HZ (0x04)\n#define MCC0G21_FSET          (0x20)\n#       define MCC0G21_FSET_8BIT        (1 << 4)\n#       define MCC0G21_FSET_TWOLINES    (1 << 3)\n#       define MCC0G21_FSET_DOUBLEH     (1 << 2)\n\n#       define MCC0G21_FSET_EXTEND      (1 << 0)\n\n#define MCC0G21_CGRAM_SELECT  (0x40)\n#define MCC0G21_DDRAM_SELECT  (0x80)\n#define MCC0G21_CONTRAST_HI   (0x50)\n#define MCC0G21_FOLLOWER      (0x60)\n#       define MCC0G21_FOLLOWER_5V      (0x0C)\n#define MCC0G21_CONTRAST_LO   (0x70)\n\n\n#define MCC0G21_COMMAND_PREFIX (0x00)\n#define MCC0G21_DATA_PREFIX    (0x40)\n\nstruct dev_disp {\n    struct i2c_slave i2c;\n    struct device *dev;\n    char buf[80];\n    uint8_t functions;\n    volatile int update;\n} Disp;\n\nstatic void mccog21_clear(void)\n{\n    uint8_t cmd = MCC0G21_CLEAR_DISPLAY;\n    int r;\n    kthread_sleep_ms(400);\n    do {\n        r = i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n    } while (r != 1);\n    kthread_sleep_ms(800);\n}\n\n/* Module description */\nint mccog21_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    if (len > 80)\n        len = 80;\n    if (len > 0)\n        memcpy(buf, Disp.buf, len);\n    return len;\n}\n\nint mccog21_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    memset(Disp.buf, 0, 80);\n    if (len > 80)\n        len = 80;\n    if (len > 0)\n        memcpy(Disp.buf, buf, len);\n\n    Disp.update = 1;\n    return len;\n}\n\nstatic struct module mod_devdisp = {\n    .family = FAMILY_FILE,\n    .name = \"lcd\",\n    .ops.open = device_open,\n    .ops.read = mccog21_read,\n    .ops.write= mccog21_write\n};\n\n\nstatic uint8_t cmd;\n\nstatic void mccog21_task(void *arg)\n{\n    (void)arg;\n    int i;\n    int r;\n\n    kthread_sleep_ms(80); /* Wait 40ms until VDD stabilizes */\n    /* Mode = 8 bit, two lines */\n    Disp.functions =  MCC0G21_FSET_8BIT | MCC0G21_FSET_TWOLINES;\n    cmd = MCC0G21_FSET | Disp.functions;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n    /* Mode = 8 bit, two lines */\n    Disp.functions =  MCC0G21_FSET_8BIT | MCC0G21_FSET_TWOLINES;\n    cmd = MCC0G21_FSET | Disp.functions;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n    /* Switch to extended mode */\n    cmd = MCC0G21_FSET | Disp.functions | MCC0G21_FSET_EXTEND;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n    /* Oscillator */\n    cmd = MCC0G21_OSC_FREQ | MCC0G21_OSC_FREQ_192HZ;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n    kthread_sleep_ms(200);\n\n    /* Follower circuit off */\n    cmd = MCC0G21_FOLLOWER | MCC0G21_FOLLOWER_5V;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n    kthread_sleep_ms(200);\n\n    /* Switch to normal mode */\n    cmd = MCC0G21_FSET | Disp.functions;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n    /* Power on */\n    cmd = MCC0G21_ONOFF | MCC0G21_DISPLAY_ON;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n\n    mccog21_clear();\n\n\n    cmd = MCC0G21_RETURN_HOME;;\n    do {\n        r = i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n    } while (r != 1);\n\n    kthread_sleep_ms(800);\n\n    cmd = MCC0G21_ENTRY_MODE | MCC0G21_ENTRY_MODE_INCREMENT;\n    do {\n        r = i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n    } while (r != 1);\n\n    /* Switch to extended mode */\n    cmd = MCC0G21_FSET | Disp.functions | MCC0G21_FSET_EXTEND;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n    /* Set contrast */\n    cmd = MCC0G21_CONTRAST_HI | 0x02;\n    do {\n        r = i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n    } while (r < 1);\n    /* Switch to normal mode */\n    cmd = MCC0G21_FSET | Disp.functions;\n    i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n\n    while(1<2) {\n        if (Disp.update) {\n            cmd = MCC0G21_RETURN_HOME;;\n            r = i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n            kthread_sleep_ms(80);\n            cmd = MCC0G21_DDRAM_SELECT;\n            i2c_kthread_write(&Disp.i2c, MCC0G21_COMMAND_PREFIX, &cmd, 1);\n\n            for (i = 0; i < 80; i++) {\n                if (Disp.buf[i] == 0)\n                    break;\n                i2c_kthread_write(&Disp.i2c, MCC0G21_DATA_PREFIX, &Disp.buf[i], 1);\n            }\n            Disp.update = 0;\n        }\n        kthread_yield();\n    }\n}\n\nint mccog21_init(uint32_t bus)\n{\n    int i;\n    struct fnode *devdir = fno_search(\"/dev\");\n    if (!devdir)\n        return -ENOENT;\n    memset(&Disp, 0, sizeof(struct dev_disp));\n    Disp.dev = device_fno_init(&mod_devdisp, \"lcd\", devdir, 0, &Disp);\n\n    /* Populate i2c_slave struct */\n    Disp.i2c.bus = bus;\n    Disp.i2c.address = MCCOG21_I2C_ADDR;\n    strcpy(Disp.buf, \"Frosted\");\n    Disp.update = 1;\n    kthread_create(mccog21_task, NULL);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/null.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"string.h\"\n\nstatic struct fnode *devnull;\nstatic struct fnode *devzero;\n\n\nstatic int devnull_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    if (fno == devnull)\n        return -EPERM;\n    if (len <= 0)\n        return len;\n    memset(buf, 0, sizeof(len));\n    return (int)len;\n}\n\n\nstatic int devnull_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    if (fno == devzero)\n        return -EPERM;\n    if (len <= 0)\n        return len;\n    return len;\n}\n\nstatic int devnull_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    return 1;\n}\n\nstatic int devnull_open(const char *path, int flags)\n{\n    struct fnode *f = fno_search(path);\n    return task_filedesc_add(f);\n\n}\n\n\n\nstatic struct module mod_devnull = {\n};\n\n\nvoid devnull_init(struct fnode *dev)\n{\n    strcpy(mod_devnull.name,\"devnull\");\n    mod_devnull.family = FAMILY_FILE;\n    mod_devnull.ops.open = devnull_open;\n    mod_devnull.ops.read = devnull_read;\n    mod_devnull.ops.poll = devnull_poll;\n    mod_devnull.ops.write = devnull_write;\n\n    devnull = fno_create_wronly(&mod_devnull, \"null\", dev);\n    devnull->flags |= FL_TTY;\n    devzero = fno_create_rdonly(&mod_devnull, \"zero\", dev);\n    devzero->flags |= FL_TTY;\n    register_module(&mod_devnull);\n}\n"
  },
  {
    "path": "kernel/drivers/pty.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include \"poll.h\"\n#include \"cirbuf.h\"\n#include <stdint.h>\n\n#define PTS_BUFSIZE (256)\n\n\nstatic struct devptmx {\n    struct device *dev;\n    uint16_t pty_idx;\n    struct fnode PTMX_ROOT;\n} PTMX;\n\n\n\nstruct devpty {\n    struct fnode *fno;\n    struct devpts *slave;\n    struct task *task;\n    uint16_t idx;\n    uint16_t creator_pid;\n    int sid;\n};\n\nstruct devpts {\n    struct device *dev;\n    struct task *task;\n    struct devpty *master;\n    struct cirbuf *miso, *mosi;\n    int sid;\n};\n\nint ptmx_open(const char *path, int flags);\nint pty_open(const char *path, int flags);\nstatic int pty_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int pty_poll(struct fnode *fno, uint16_t events, uint16_t *revents);\nstatic int pty_write(struct fnode *fno, const void *buf, unsigned int len);\nstatic void pty_tty_attach(struct fnode *fno, int pid);\nstatic int pty_close(struct fnode *fno);\nstatic int pts_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int pts_poll(struct fnode *fno, uint16_t events, uint16_t *revents);\nstatic int pts_write(struct fnode *fno, const void *buf, unsigned int len);\nstatic void pts_tty_attach(struct fnode *fno, int pid);\nstatic int pts_close(struct fnode *fno);\n\nstatic struct module mod_ptmx = {\n    .family = FAMILY_DEV,\n    .name = \"ptmx\",\n    .ops.open = ptmx_open,\n};\n\nstatic struct module mod_devpty = {\n    .family = FAMILY_DEV,\n    .name = \"pty\",\n    .ops.open = pty_open,\n    .ops.read = pty_read,\n    .ops.poll = pty_poll,\n    .ops.write = pty_write,\n    .ops.tty_attach = pty_tty_attach,\n    .ops.close = pty_close\n\n};\n\nstatic struct module mod_devpts = {\n    .family = FAMILY_DEV,\n    .name = \"pts\",\n    .ops.open = device_open,\n    .ops.read = pts_read,\n    .ops.poll = pts_poll,\n    .ops.write = pts_write,\n    .ops.tty_attach = pts_tty_attach\n};\n\nstatic int pts_create(void)\n{\n    int idx = PTMX.pty_idx++;\n    struct devpts *pts;\n    struct devpty *pty = kalloc(sizeof(struct devpty));\n    char name[3];\n    if (!pty)\n        return -ENOMEM;\n    pts = kalloc(sizeof(struct devpts));\n    if (!pts) {\n        kfree(pty);\n        return -ENOMEM;\n    }\n\n    if (idx < 10) {\n        name[0] = '0' + idx;\n        name[1] = '\\0';\n    } else {\n        name[0] = '0' + idx / 10;\n        name[1] = '0' + (idx % 10);\n        name[2] = '\\0';\n    }\n    pts->miso = cirbuf_create(PTS_BUFSIZE);\n    pts->mosi = cirbuf_create(PTS_BUFSIZE);\n    pts->dev = device_fno_init(&mod_devpts, name, fno_search(\"/dev/pts\"), FL_TTY, pts);\n    pts->master = pty;\n    pty->idx = idx;\n    pty->fno = fno_create(&mod_devpty, \"\", &PTMX.PTMX_ROOT); \n    pty->fno->flags |= FL_TTY;\n    pty->fno->priv = pty;\n    pty->slave = pts;\n    pty->task = NULL;\n    pts->task = NULL;\n    pty->sid = -1;\n    pts->sid = -1;\n    pty->creator_pid = this_task_getpid();\n    return task_filedesc_add(pty->fno);\n}\n\nstatic void ptmx_create(void) \n{\n    char name[5] = \"ptmx\";\n    struct fnode *devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return;\n    fno_mkdir(&mod_devpts, \"pts\", devfs);\n    PTMX.dev = device_fno_init(&mod_ptmx, name, devfs, FL_TTY, &PTMX);\n    PTMX.pty_idx = 0;\n    memset(&PTMX.PTMX_ROOT, 0, sizeof(struct fnode));\n}\n\nint ptmx_init(void)\n{\n    ptmx_create();\n    return 0;\n}\n\nint pty_open(const char *path, int flags)\n{\n    return -EINVAL;\n}\n\nint ptmx_open(const char *path, int flags)\n{\n    struct fnode *f = fno_search(path);\n    struct fnode *master, *slave;\n    if (f != PTMX.dev->fno)\n        return -EINVAL;\n    return pts_create();\n}\n\nstatic int pty_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = -EINVAL;\n    if (len == 0)\n        return 0;\n    pty = (struct devpty *)FNO_MOD_PRIV(fno, &mod_devpty);\n    if (pty)\n        pts = pty->slave;\n    if (pts) {\n        mutex_lock(pts->dev->mutex);\n        if (pts->master != pty)\n            ret = -EPIPE;\n        if (cirbuf_bytesinuse(pts->miso) > 0) {\n            ret = cirbuf_readbytes(pts->miso, buf, len);\n            if ((ret > 0) && pts->task)\n                task_resume(pts->task);\n        } else {\n            pty->task = this_task();\n            task_suspend();\n            ret = SYS_CALL_AGAIN;\n        }\n        mutex_unlock(pts->dev->mutex);\n    }\n    return ret;\n}\n\nstatic int pty_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = -EINVAL;\n    pty = (struct devpty *)FNO_MOD_PRIV(fno, &mod_devpty);\n    if (pty)\n        pts = pty->slave;\n    if (pts) {\n        mutex_lock(pts->dev->mutex);\n        if (pts->master != pty)\n            ret = -EPIPE;\n        if (cirbuf_bytesfree(pts->mosi) > 0) {\n            ret = cirbuf_writebytes(pts->mosi, buf, len);\n            if ((ret > 0) && pts->task)\n                task_resume(pts->task);\n        } else {\n            pty->task = this_task();\n            task_suspend();\n            ret = SYS_CALL_AGAIN;\n        }\n        mutex_unlock(pts->dev->mutex);\n    }\n    return ret;\n}\n\nstatic int pty_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = 0;\n    pty = (struct devpty *)FNO_MOD_PRIV(fno, &mod_devpty);\n\n    if (!pty)\n        return -EINVAL;\n    if (pty)\n        pts = pty->slave;\n\n    if (!pts)\n        return -EPIPE;\n\n    mutex_lock(pts->dev->mutex);\n    if (pts->master != pty)\n        ret = -EPIPE;\n    if ((events & POLLOUT) && (cirbuf_bytesfree(pts->mosi) > 0)) {\n        *revents |= POLLOUT;\n        ret = 1;\n    }\n    if ((events & POLLIN) && (cirbuf_bytesinuse(pts->miso) > 0)) {\n        *revents |= POLLIN;\n        ret = 1;\n    }\n    if (ret == 0) {\n        pty->task = this_task();\n    }\n    mutex_unlock(pts->dev->mutex);\n    return ret;\n}\n\nstatic void pty_tty_attach(struct fnode *fno, int pid)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = 0;\n    pty = (struct devpty *)FNO_MOD_PRIV(fno, &mod_devpty);\n    if (pty->sid != pid) {\n        pty->sid = pid;\n    }\n}\n\nstatic int pty_close(struct fnode *fno)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = 0;\n    pty = (struct devpty *)FNO_MOD_PRIV(fno, &mod_devpty);\n    if (!pty)\n        return -1;\n    pts = pty->slave;\n    if (!pts)\n        return -1;\n\n    if (this_task_getpid() == pty->creator_pid) {\n        mutex_lock(pts->dev->mutex);\n        fno_unlink(pts->dev->fno);\n        pty->fno->priv = NULL;\n        pts->dev->fno->priv = NULL;\n        kfree(pty);\n        pts->master = NULL;\n        mutex_unlock(pts->dev->mutex);\n        kfree(pts);\n    }\n    return 0;\n}\n\n\nint pts_open(const char *path, int flags)\n{\n    struct fnode *f = fno_search(path);\n    struct fnode *master, *slave;\n    if (f != PTMX.dev->fno)\n        return -EINVAL;\n    return pts_create();\n}\n\nstatic int pts_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = -EINVAL;\n    if (len == 0)\n        return 0;\n    pts = (struct devpts *)FNO_MOD_PRIV(fno, &mod_devpts);\n    if (!pts)\n        goto out;\n    mutex_lock(pts->dev->mutex);\n    pty = pts->master;\n    if (!pty) {\n        ret = -EPIPE;\n        goto out;\n    }\n    if (cirbuf_bytesinuse(pts->mosi) > 0) {\n        ret = cirbuf_readbytes(pts->mosi, buf, len);\n        if ((ret > 0) && pty->task)\n            task_resume(pty->task);\n    } else {\n        pts->task = this_task();\n        task_suspend();\n        ret = SYS_CALL_AGAIN;\n    }\nout:\n    mutex_unlock(pts->dev->mutex);\n    return ret;\n}\n\nstatic int pts_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = -EINVAL;\n    pts = (struct devpts *)FNO_MOD_PRIV(fno, &mod_devpts);\n    if (!pts)\n        goto out;\n    mutex_lock(pts->dev->mutex);\n    pty = pts->master;\n    if (!pty) {\n        ret = -EPIPE;\n        goto out;\n    }\n    if (cirbuf_bytesfree(pts->miso) > 0) {\n        ret = cirbuf_writebytes(pts->miso, buf, len);\n        if ((ret > 0) && pty->task)\n            task_resume(pty->task);\n    } else {\n        pts->task = this_task();\n        task_suspend();\n        ret = SYS_CALL_AGAIN;\n    }\nout:\n    mutex_unlock(pts->dev->mutex);\n    return ret;\n}\n\nstatic int pts_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    int ret = -EINVAL;\n    pts = (struct devpts *)FNO_MOD_PRIV(fno, &mod_devpts);\n    if (!pts)\n        goto out;\n    mutex_lock(pts->dev->mutex);\n    pty = pts->master;\n    if (!pty) {\n        ret = -EPIPE;\n        goto out;\n    }\n\n    ret = 0;\n\n    if ((events & POLLOUT) && (cirbuf_bytesfree(pts->miso) > 0)) {\n        *revents |= POLLOUT;\n        ret = 1;\n    }\n    if ((events & POLLIN) && (cirbuf_bytesinuse(pts->mosi) > 0)) {\n        *revents |= POLLIN;\n        ret = 1;\n    }\n    if (ret == 0) {\n        pts->task = this_task();\n    }\nout:\n    mutex_unlock(pts->dev->mutex);\n    return ret;\n}\n\nstatic void pts_tty_attach(struct fnode *fno, int pid)\n{\n    struct devpts *pts = NULL;\n    int ret = 0;\n    pts = (struct devpts *)FNO_MOD_PRIV(fno, &mod_devpts);\n    if (pts->sid != pid) {\n        pts->sid = pid;\n    }\n}\n\nint sys_ptsname_hdlr(int fd, char *buf, size_t buflen)\n{\n    struct devpty *pty = NULL;\n    struct devpts *pts = NULL;\n    struct fnode *fno = task_filedesc_get(fd);\n    size_t pathlen = strlen(\"/dev/pts/\");\n    if (fd < 0 || !buf)\n        return -EINVAL;\n\n    if (task_ptr_valid(buf))\n        return -EACCES;\n\n    if (buflen < pathlen + 3)\n        return -EINVAL;\n    pty = (struct devpty *)FNO_MOD_PRIV(fno, &mod_devpty);\n    if (!pty)\n        return -ENOTTY;\n\n    strcpy(buf, \"/dev/pts/\");\n    if (pty->idx > 9) {\n        buf[pathlen++] = pty->idx / 10;\n    }\n    buf[pathlen++] = pty->idx % 10;\n    buf[pathlen] = '\\0';\n    return 0;\n}\n\n"
  },
  {
    "path": "kernel/drivers/pty.h",
    "content": "#ifndef PTY_H_INCLUDED\n#define PTY_H_INCLUDED\n\n#ifndef CONFIG_PTY_UNIX\n#   define ptmx_init() do{}while(0)\n#else\n    int ptmx_init(void);\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/rng.h",
    "content": "#ifndef RNG_INC\n#define RNG_INC\n#include \"frosted.h\"\n\n#ifdef CONFIG_RNG\n\nint rng_init(void);\nint rng_create(uint32_t base, uint32_t rcc);\n\n#else\n\n#define rng_init() (-ENOENT)\n#define rng_create(...) (-ENOENT)\n\n#endif\n\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/sdio.h",
    "content": "#ifndef INC_SDIO\n#define INC_SDIO\n#include \"frosted.h\"\n#include \"gpio.h\"\n\nstruct sdio_config {\n    uint32_t *base;\n    uint32_t devidx;\n    uint32_t *rcc_reg;\n    uint32_t rcc_en;\n    uint32_t *rcc_rst_reg;\n    uint32_t rcc_rst;\n\n    struct gpio_config pio_dat0, pio_dat1, pio_dat2, pio_dat3;\n    struct gpio_config pio_clk, pio_cmd;\n\n    int card_detect_supported;\n    struct gpio_config pio_cd;\n};\n\n#ifdef CONFIG_SDIO\nint sdio_init(struct sdio_config *conf);\n#else\n#define sdio_init(x) (-ENOENT)\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/sdram.h",
    "content": "#ifndef INC_SDRAM\n#define INC_SDRAM\n\n#if defined CONFIG_SDRAM\nint sdram_init(void);\n#else\n#define sdram_init() (-ENOENT)\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/socket_in.c",
    "content": "#include \"frosted.h\"\n#include \"socket_in.h\"\n#include <string.h>\n#include <sys/types.h>\n#include <net/if.h>\n#include <net/route.h>\n#include <sys/ioctl.h>\n#include <pico_device.h>\n\nstatic struct module mod_socket_in;\n\nstruct frosted_inet_socket {\n    struct fnode *node;\n    struct pico_socket *sock;\n    struct task *task;\n    int fd;\n    uint16_t events;\n    uint16_t revents;\n    int bytes;\n};\n\n#define SOCK_BLOCKING(s) (((s->node->flags & O_NONBLOCK) == 0))\n\n\n\nstatic int sock_check_fd(int fd, struct fnode **fno)\n{\n    *fno = task_filedesc_get(fd);\n\n    if (!fno)\n        return -1;\n\n    if (fd < 0)\n        return -1;\n    if ((*fno)->owner != &mod_socket_in)\n        return -1;\n\n    return 0;\n}\n\nstatic int sock_poll(struct fnode *f, uint16_t events, uint16_t *revents)\n{\n    struct frosted_inet_socket *s;\n    s = (struct frosted_inet_socket *)f->priv;\n\n    if (s->revents & PICO_SOCK_EV_CLOSE)\n        *revents |= POLLHUP;\n\n    if (s->revents & PICO_SOCK_EV_FIN)\n        *revents |= POLLERR;\n\n    if (s->revents & PICO_SOCK_EV_CONN)\n        *revents |= POLLIN;\n\n    if (s->revents & PICO_SOCK_EV_RD)\n        *revents |= POLLIN;\n\n    if (s->revents & PICO_SOCK_EV_WR)\n        *revents |= POLLOUT;\n\n    if ((*revents) & (POLLHUP | POLLERR) != 0) {\n        return 1;\n    }\n    if ((events & *revents) != 0)\n        return 1;\n\n    s->events |= events;\n    s->task = this_task();\n    return 0;\n}\n\nstatic struct frosted_inet_socket *fd_inet(int fd)\n{\n    struct fnode *fno;\n    struct frosted_inet_socket *s;\n    if (sock_check_fd(fd, &fno) != 0)\n        return NULL;\n\n    s = (struct frosted_inet_socket *)fno->priv;\n    return s;\n}\n\nstatic struct frosted_inet_socket *pico_inet(struct pico_socket *s)\n{\n    if (!s || !s->priv)\n        return NULL;\n    return (struct frosted_inet_socket *)(s->priv);\n}\n\nstatic void pico_socket_event(uint16_t ev, struct pico_socket *sock)\n{\n    struct frosted_inet_socket *s;\n    s = pico_inet(sock);\n    if (!s) {\n        return;\n    }\n    s->revents |= ev;\n    if ((s->revents & s->events) != 0) {\n        task_resume(s->task);\n        s->events = 0;\n    }\n}\n\nstatic int sock_close(struct fnode *fno)\n{\n    struct frosted_inet_socket *s;\n    int ret = -1;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    if (!fno) {\n        ret = -1;\n        goto out;\n    }\n    s = (struct frosted_inet_socket *)fno->priv;\n    if (!s) {\n        ret = -1;\n        goto out;\n    }\n    if (pico_trylock() < 0) {\n        ret = SYS_CALL_AGAIN;\n        goto out;\n    }\n    pico_socket_close(s->sock);\n    pico_unlock();\n    kfree((struct fnode *)s->node);\n    kfree(s);\n    ret = 0;\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic struct frosted_inet_socket *inet_socket_new(uint32_t flags)\n{\n    struct frosted_inet_socket *s;\n    s = kcalloc(sizeof(struct frosted_inet_socket), 1);\n    if (!s)\n        return NULL;\n    s->node = kcalloc(sizeof(struct fnode), 1);\n    if (!s->node) {\n        kfree(s);\n        return NULL;\n    }\n    s->node->flags = FL_RDWR | flags;\n    return s;\n}\n\nstatic int sock_socket(int domain, int type_flags, int protocol)\n{\n    int fd = -1;\n    struct frosted_inet_socket *s;\n    int type = type_flags & 0xFFFF;\n    uint32_t fnode_flags = ((uint32_t)type_flags) & 0xFFFF0000u;\n    int ret = -1;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    s = inet_socket_new(fnode_flags);\n    if (!s) {\n        ret = -ENOMEM;\n        goto out;\n    }\n    if (domain != PICO_PROTO_IPV4)\n        domain = PICO_PROTO_IPV4;\n\n    if (type == 1)\n        type = PICO_PROTO_TCP;\n\n    if (type == 2) {\n        if ((protocol == 0) || (protocol == IPPROTO_UDP)) {\n            type = PICO_PROTO_UDP;\n        } else if (protocol == IPPROTO_ICMP) {\n            type = PICO_PROTO_ICMP4;\n        } else {\n            kfree((struct fnode *)s->node);\n            kfree(s);\n            return -EPROTONOSUPPORT;\n        }\n    }\n\n    if (pico_trylock() < 0) {\n        ret = SYS_CALL_AGAIN;\n        goto out;\n    }\n    s->sock = pico_socket_open(domain, type, pico_socket_event);\n    if (s)\n        s->sock->priv = s;\n    pico_unlock();\n    if (!s->sock) {\n        kfree((struct fnode *)s->node);\n        kfree(s);\n        ret = 0 - pico_err;\n        goto out;\n    }\n    s->node->owner = &mod_socket_in;\n    s->node->priv = s;\n    s->fd = task_filedesc_add(s->node);\n    if (s->fd >= 0)\n        task_fd_setmask(s->fd, O_RDWR);\n    ret = s->fd;\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_recvfrom(int fd, void *buf, unsigned int len, int flags, struct sockaddr *addr, unsigned int *addrlen)\n{\n    struct frosted_inet_socket *s;\n    int ret;\n    uint16_t port;\n    struct pico_ip4 paddr;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    s = fd_inet(fd);\n    if (!s)\n        return -EINVAL;\n    while (s->bytes < len) {\n        if ((addr) && ((*addrlen) > 0)) {\n            if (pico_trylock() < 0) {\n                ret = SYS_CALL_AGAIN;\n                goto out;\n            }\n            ret = pico_socket_recvfrom(s->sock, buf + s->bytes, len - s->bytes, &paddr, &port);\n            pico_unlock();\n        } else {\n            if (pico_trylock() < 0) {\n                return SYS_CALL_AGAIN;\n            }\n            ret = pico_socket_read(s->sock, buf + s->bytes, len - s->bytes);\n            pico_unlock();\n        }\n\n        if (ret < 0) {\n            ret = 0 - pico_err;\n            goto out;\n        }\n\n        if (ret == 0) {\n            s->revents &= (~PICO_SOCK_EV_RD);\n            if (SOCK_BLOCKING(s))  {\n                s->events = PICO_SOCK_EV_RD;\n                s->task = this_task();\n                task_suspend();\n                ret = SYS_CALL_AGAIN;\n                goto out;\n            }\n            break;\n        }\n        s->bytes += ret;\n        if (s->bytes > 0)\n            break;\n    }\n    if (addr) {\n        ((struct sockaddr_in *)addr)->sin_family = AF_INET;\n        ((struct sockaddr_in *)addr)->sin_port = port;\n        ((struct sockaddr_in *)addr)->sin_addr.s_addr = paddr.addr;\n    }\n    ret = s->bytes;\n    s->bytes = 0;\n    s->events  &= (~PICO_SOCK_EV_RD);\n    s->revents &= (~PICO_SOCK_EV_RD);\n    if ((ret == 0) && !SOCK_BLOCKING(s)) {\n        ret = -EAGAIN;\n    }\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_sendto(int fd, const void *buf, unsigned int len, int flags, struct sockaddr *addr, unsigned int addrlen)\n{\n    struct frosted_inet_socket *s;\n    uint16_t port;\n    struct pico_ip4 paddr;\n    int ret;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    s = fd_inet(fd);\n    if (!s) {\n        ret = -EINVAL;\n        goto out;\n    }\n\n\n    while (len > s->bytes) {\n        if ((addr) && (addrlen >0))\n        {\n            if (pico_trylock() < 0) {\n                ret = SYS_CALL_AGAIN;\n                goto out;\n            }\n            paddr.addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;\n            port = ((struct sockaddr_in *)addr)->sin_port;\n            ret = pico_socket_sendto(s->sock, buf + s->bytes, len - s->bytes, &paddr, port);\n            pico_unlock();\n        } else {\n            if (pico_trylock() < 0) {\n                ret = SYS_CALL_AGAIN;\n                goto out;\n            }\n            ret = pico_socket_write(s->sock, buf + s->bytes, len - s->bytes);\n            pico_unlock();\n        }\n        if (ret == 0) {\n            s->revents &= (~PICO_SOCK_EV_WR);\n            if (SOCK_BLOCKING(s)) {\n                s->events = PICO_SOCK_EV_WR;\n                s->task = this_task();\n                task_suspend();\n                ret = SYS_CALL_AGAIN;\n                goto out;\n            }\n        }\n        if (ret < 0) {\n            ret = (0 - pico_err);\n            goto out;\n        }\n\n        s->bytes += ret;\n        if ((s->sock->proto->proto_number) == PICO_PROTO_UDP && (s->bytes > 0))\n            break;\n    }\n    ret = s->bytes;\n    s->bytes = 0;\n    s->events  &= (~PICO_SOCK_EV_WR);\n    if ((ret == 0) && !SOCK_BLOCKING(s)) {\n        ret = -EAGAIN;\n    }\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_bind(int fd, struct sockaddr *addr, unsigned int addrlen)\n{\n    struct frosted_inet_socket *s;\n    union pico_address paddr;\n    uint16_t port;\n    int ret;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    s = fd_inet(fd);\n    if (!s) {\n        ret =  -EINVAL;\n        goto out;\n    }\n    paddr.ip4.addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;\n    port = ((struct sockaddr_in *)addr)->sin_port;\n    if (pico_trylock() < 0) {\n        ret = SYS_CALL_AGAIN;\n        goto out;\n    }\n    ret = pico_socket_bind(s->sock, &paddr, &port);\n    pico_unlock();\n    if (ret == 0) {\n        ((struct sockaddr_in *)addr)->sin_port = port;\n    } else {\n        ret = 0 - pico_err;\n    }\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_accept(int fd, struct sockaddr *addr, unsigned int *addrlen)\n{\n    struct frosted_inet_socket *l, *s;\n    struct pico_socket *cli;\n    union pico_address paddr;\n    uint16_t port;\n    struct sockaddr_in *s_in = (struct sockaddr_in *)addr;\n    int ret = -1;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    l = fd_inet(fd);\n    if (!l) {\n        ret = -EINVAL;\n        goto out;\n    }\n    l->events = PICO_SOCK_EV_CONN;\n\n    if (pico_trylock() < 0) {\n        ret = SYS_CALL_AGAIN;\n        goto out;\n    }\n    cli = pico_socket_accept(l->sock, &paddr, &port);\n    pico_unlock();\n    if ((cli == NULL) && (pico_err != PICO_ERR_EAGAIN)) {\n        ret = 0 - pico_err;\n        goto out;\n    }\n\n    l->revents &= (~PICO_SOCK_EV_CONN);\n    if (cli) {\n        s = inet_socket_new(0);\n        if (!s) {\n            if (pico_trylock() < 0) {\n                ret = SYS_CALL_AGAIN;\n                goto out;\n            }\n            pico_socket_close(cli);\n            pico_unlock();\n            ret = -ENOMEM;\n            goto out;\n        }\n        s->sock = cli;\n        s->node->owner = &mod_socket_in;\n        s->node->priv = s;\n        s->sock->priv = s;\n        s->fd = task_filedesc_add(s->node);\n        if (s->fd >= 0)\n            task_fd_setmask(s->fd, O_RDWR);\n        if (s_in) {\n            s_in->sin_family = AF_INET;\n            s_in->sin_port = port;\n            s_in->sin_addr.s_addr = paddr.ip4.addr;\n        }\n        ret = s->fd;\n        goto out;\n    } else {\n        if (SOCK_BLOCKING(l)) {\n            l->task = this_task();\n            task_suspend();\n            ret = SYS_CALL_AGAIN;\n        } else {\n            ret = -EAGAIN;\n        }\n    }\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_connect(int fd, struct sockaddr *addr, unsigned int addrlen)\n{\n    struct frosted_inet_socket *s;\n    union pico_address paddr;\n    uint16_t port;\n    int ret = -1;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    s = fd_inet(fd);\n    if (!s) {\n        ret = -EINVAL;\n        goto out;\n    }\n\n    s->events = PICO_SOCK_EV_CONN;\n    if ((s->revents & PICO_SOCK_EV_CONN) == 0) {\n        paddr.ip4.addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;\n        port = ((struct sockaddr_in *)addr)->sin_port;\n        if (pico_trylock() < 0) {\n            ret = SYS_CALL_AGAIN;\n            goto out;\n        }\n        ret = pico_socket_connect(s->sock, &paddr, port);\n        pico_unlock();\n        if (SOCK_BLOCKING(s)) {\n            s->task = this_task();\n            ret = SYS_CALL_AGAIN;\n        } else {\n            ret = -EAGAIN;\n        }\n        goto out;\n    }\n\n    /* SOCK_EV_CONN received. Successfully connected. */\n    ret = 0;\n    s->events  &= (~PICO_SOCK_EV_CONN);\n    s->revents &= ~(PICO_SOCK_EV_CONN | PICO_SOCK_EV_RD);\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_listen(int fd, int backlog)\n{\n    struct frosted_inet_socket *s;\n    int ret;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    s = fd_inet(fd);\n    if (!s) {\n        ret = -EINVAL;\n        goto out;\n    }\n    if (pico_trylock() < 0) {\n        ret = SYS_CALL_AGAIN;\n        goto out;\n    }\n    ret = pico_socket_listen(s->sock, backlog);\n    pico_unlock();\n    s->events |= PICO_SOCK_EV_CONN;\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_shutdown(int fd, uint16_t how)\n{\n    struct frosted_inet_socket *s;\n    int ret;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    s = fd_inet(fd);\n    if (!s) {\n        ret = -EINVAL;\n        goto out;\n    }\n    if (pico_trylock() < 0) {\n        ret = SYS_CALL_AGAIN;\n        goto out;\n    }\n    ret =  pico_socket_shutdown(s->sock, how);\n    pico_unlock();\nout:\n    mem_unlock();\n    return ret;\n}\n\n\nstatic int sock_io_setflags(struct pico_device *dev, struct ifreq *ifr)\n{\n    unsigned int flags = ifr->ifr_flags;\n    if ((flags & IFF_UP) == 0)\n        pico_device_destroy(dev);\n\treturn 0;\n}\n\nstatic int sock_io_setaddr(struct pico_device *dev, struct ifreq *ifr)\n{\n    struct pico_ipv4_link *l;\n    const struct pico_ip4 NM24 = {.addr = long_be(0xFFFFFF00)};\n    struct sockaddr_in *if_addr = ((struct sockaddr_in *) &ifr->ifr_addr);\n    struct pico_ip4 dev_addr = {};\n\n    l = pico_ipv4_link_by_dev(dev);\n    if (l) {\n        pico_ipv4_link_del(dev, l->address);\n    }\n    dev_addr.addr = if_addr->sin_addr.s_addr;\n    return pico_ipv4_link_add(dev, dev_addr, NM24);\n}\n\nstatic int sock_io_setnetmask(struct pico_device *dev, struct ifreq *ifr)\n{\n    struct pico_ipv4_link *l;\n    struct sockaddr_in *if_nmask = ((struct sockaddr_in *) &ifr->ifr_netmask);\n    struct pico_ip4 dev_addr = {};\n    struct pico_ip4 dev_nm = {};\n\n    l = pico_ipv4_link_by_dev(dev);\n    if (!l)\n        return -ENOTCONN;\n    dev_addr.addr = l->address.addr;\n    pico_ipv4_link_del(dev, l->address);\n    dev_nm.addr = if_nmask->sin_addr.s_addr;\n    return pico_ipv4_link_add(dev, dev_addr, dev_nm);\n}\n\nstatic int sock_io_getflags(struct pico_device *dev, struct ifreq *ifr)\n{\n    memset(ifr, 0, sizeof(struct ifreq));\n    strncpy(ifr->ifr_name, dev->name, IFNAMSIZ);\n    ifr->ifr_flags = IFF_UP|IFF_RUNNING|IFF_MULTICAST|IFF_BROADCAST;\n\treturn 0;\n}\n\nstatic int sock_io_getaddr(struct pico_device *dev, struct ifreq *ifr)\n{\n    struct pico_ipv4_link *l;\n    struct sockaddr_in *if_addr = ((struct sockaddr_in *) &ifr->ifr_addr);\n    memset(ifr, 0, sizeof(struct ifreq));\n    strncpy(ifr->ifr_name, dev->name, IFNAMSIZ);\n    l = pico_ipv4_link_by_dev(dev);\n    if (!l)\n    \treturn 0;\n    ifr->ifr_flags = IFF_UP|IFF_RUNNING|IFF_MULTICAST|IFF_BROADCAST;\n    memset(if_addr, 0, sizeof(struct sockaddr_in));\n    if_addr->sin_family = AF_INET;\n    if_addr->sin_addr.s_addr = l->address.addr;\n    return 0;\n}\n\nstatic int sock_io_gethwaddr(struct pico_device *dev, struct ifreq *eth)\n{\n    if (!dev->eth)\n        return -EPROTONOSUPPORT;\n    /* TODO\n    memset(eth, 0, sizeof(struct ifreq));\n    strncpy(eth->ifr_name, dev->name, IFNAMSIZ);\n    eth->ifr_flags = IFF_UP|IFF_RUNNING|IFF_MULTICAST|IFF_BROADCAST;\n    eth->ifr_hwaddr.sa_family = ARPHRD_ETHER;\n    memcpy (&eth->ifr_hwaddr.sa_data, dev->eth, 6);\n    */\n\treturn 0;\n\n}\n\nstatic int sock_io_getbcast(struct pico_device *dev, struct ifreq *ifr)\n{\n    struct pico_ipv4_link *l;\n    struct sockaddr_in *if_addr = ((struct sockaddr_in *) &ifr->ifr_broadaddr);\n\n    memset(if_addr, 0, sizeof(struct sockaddr_in));\n    if_addr->sin_addr.s_addr = 0xFFFFFFFF;\n    l = pico_ipv4_link_by_dev(dev);\n    if (!l)\n    \treturn 0;\n    if_addr->sin_family = AF_INET;\n    if_addr->sin_addr.s_addr = (l->address.addr & l->netmask.addr) | (~l->netmask.addr);\n    return 0;\n}\n\nstatic int sock_io_getnmask(struct pico_device *dev, struct ifreq *ifr)\n{\n    struct pico_ipv4_link *l;\n    struct sockaddr_in *if_nmask = ((struct sockaddr_in *) &ifr->ifr_netmask);\n    l = pico_ipv4_link_by_dev(dev);\n    memset(if_nmask, 0, sizeof(struct sockaddr_in));\n    if (!l)\n    \treturn 0;\n    if_nmask->sin_family = AF_INET;\n    if_nmask->sin_addr.s_addr = l->netmask.addr;\n    return 0;\n}\n\nstatic int sock_io_addroute(struct rtentry *rte)\n{\n  struct pico_ip4 a, g, n;\n  struct pico_ipv4_link *link = NULL;\n  int flags = 1;\n  struct pico_device *dev;\n\n  dev = pico_get_device((char *)rte->rt_dev);\n  if (dev)\n    link = pico_ipv4_link_by_dev(dev);\n\n  memcpy(&a, &((struct sockaddr_in *)(&rte->rt_dst))->sin_addr.s_addr, sizeof(struct pico_ip4));\n  memcpy(&g, &((struct sockaddr_in *)(&rte->rt_gateway))->sin_addr.s_addr, sizeof(struct pico_ip4));\n  memcpy(&n, &((struct sockaddr_in *)(&rte->rt_genmask))->sin_addr.s_addr, sizeof(struct pico_ip4));\n  a.addr &= n.addr;\n\n  if (n.addr == 0)\n      flags +=2;\n\n  if (rte->rt_metric <= 0)\n      rte->rt_metric = 1;\n\n  if (pico_ipv4_route_add(a, n, g, rte->rt_metric, link) < 0)\n    return 0 - pico_err;\n  return 0;\n}\n\nstatic int sock_io_delroute(struct rtentry *rte)\n{\n  struct pico_ip4 a, g, n;\n  int flags = 1;\n\n\n  memcpy(&a, &((struct sockaddr_in *)(&rte->rt_dst))->sin_addr.s_addr, sizeof(struct pico_ip4));\n  memcpy(&n, &((struct sockaddr_in *)(&rte->rt_genmask))->sin_addr.s_addr, sizeof(struct pico_ip4));\n  a.addr &= n.addr;\n\n  if (n.addr == 0)\n      flags +=2;\n\n  if (rte->rt_metric <= 0)\n      rte->rt_metric = 1;\n\n  if (pico_ipv4_route_del(a, n, rte->rt_metric) < 0)\n    return 0 - pico_err;\n  return 0;\n}\n\n\nstatic int sock_io_ethtool(struct pico_device *dev, struct ifreq *ifr)\n{\n\treturn 0;\n}\n\nstatic int sock_ioctl(struct fnode *fno, const uint32_t cmd, void *arg)\n{\n\n    struct frosted_inet_socket *s;\n    struct ifreq *ifr;\n    struct pico_device *dev;\n    int ret = -ENOENT;\n\n    if (!fno || !arg)\n        return -EINVAL;\n\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    /* Check for route commands */\n    if (cmd == SIOCADDRT)\n    {\n        struct rtentry *rte = (struct rtentry *)arg;\n        ret = sock_io_addroute(rte);\n    }\n    else if (cmd == SIOCDELRT)\n    {\n        struct rtentry *rte = (struct rtentry *)arg;\n        ret =  sock_io_delroute(rte);\n    } else {\n\n        /* Check for interface-related ioctl */\n        ifr = (struct ifreq *)arg;\n        dev = pico_get_device(ifr->ifr_name);\n        if (!dev)\n            ret = -ENOENT;\n        else {\n\n            switch(cmd) {\n                case SIOCSIFFLAGS:\n                    ret = sock_io_setflags(dev, ifr);\n                    break;\n                case SIOCSIFADDR:\n                    ret = sock_io_setaddr(dev, ifr);\n                    break;\n                case SIOCSIFNETMASK:\n                    ret = sock_io_setnetmask(dev, ifr);\n                    break;\n                case SIOCGIFFLAGS:\n                    ret = sock_io_getflags(dev, ifr);\n                    break;\n                case SIOCGIFADDR:\n                    ret = sock_io_getaddr(dev, ifr);\n                    break;\n                case SIOCGIFHWADDR:\n                    ret = sock_io_gethwaddr(dev, ifr);\n                    break;\n                case SIOCGIFBRDADDR:\n                    ret = sock_io_getbcast(dev, ifr);\n                    break;\n                case SIOCGIFNETMASK:\n                    ret = sock_io_getnmask(dev, ifr);\n                    break;\n                case SIOCETHTOOL:\n                    ret = sock_io_ethtool(dev, ifr);\n                    break;\n                default:\n                    ret = -ENOSYS;\n            }\n        }\n    }\n    mem_unlock();\n    return ret;\n}\n\n\n/* /sys/net hooks */\n#define MAX_DEVNET_BUF 64\nstatic int sysfs_net_dev_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    static int off;\n    static char *txt;\n    int i;\n    struct pico_device *dev;\n    struct pico_tree_node *index = NULL;\n    const char iface_banner[] = \"Interface | \\r\\n\";\n    uint32_t cur_off = task_fd_get_off(fno);\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    sysfs_lock();\n    if (cur_off == 0) {\n        txt = kcalloc(MAX_DEVNET_BUF, 1);\n        off = 0;\n        if (!txt) {\n            len = -1;\n            goto out;\n        }\n        strcpy(txt, iface_banner);\n        off += strlen(iface_banner);\n        pico_tree_foreach(index, &Device_tree){\n            dev = index->keyValue;\n            strcat(txt, dev->name);\n            off += strlen(dev->name);\n            txt[off++] = '\\r';\n            txt[off++] = '\\n';\n        }\n    }\n    cur_off = task_fd_get_off(fno);\n    if (off == cur_off) {\n        kfree(txt);\n        len = -1;\n        goto out;\n    }\n    if (len > (off - cur_off)) {\n       len = off - cur_off;\n    }\n    memcpy(res, txt + cur_off, len);\n    cur_off += len;\n    task_fd_set_off(fno, cur_off);\nout:\n    sysfs_unlock();\n    mem_unlock();\n    return len;\n}\n\n#define MAX_SYSFS_BUFFER 512\nint sysfs_net_route_list(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    static char *mem_txt;\n    struct pico_ipv4_route *r;\n    struct pico_tree_node *index = NULL;\n    char dest[16];\n    char mask[16];\n    char gw[16];\n    char metric[5];\n    static int off;\n    int i;\n    uint32_t cur_off = task_fd_get_off(fno);\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    if (cur_off == 0) {\n        const char route_banner[] = \"Kernel IP routing table\\r\\nDestination     Gateway         Genmask         Flags   Metric  Iface \\r\\n\";\n        sysfs_lock();\n        mem_txt = kalloc(MAX_SYSFS_BUFFER);\n        if (!mem_txt)\n            return -1;\n        off = 0;\n        strcpy(mem_txt + off, route_banner);\n        off += strlen(route_banner);\n        pico_tree_foreach(index, &Routes){\n\n            r = index->keyValue;\n\n            /* Destination */\n            pico_ipv4_to_string(dest, r->dest.addr);\n            strcpy(mem_txt + off, dest);\n            off+=strlen(dest);\n            mem_txt[off++] = '\\t';\n            if (strlen(dest) < 8)\n                mem_txt[off++] = '\\t';\n\n            /* Gateway */\n            pico_ipv4_to_string(gw, r->gateway.addr);\n            strcpy(mem_txt + off, gw);\n            off+=strlen(gw);\n            mem_txt[off++] = '\\t';\n            if (strlen(gw) < 8)\n                mem_txt[off++] = '\\t';\n\n            /* Genmask */\n            pico_ipv4_to_string(mask, r->netmask.addr);\n            strcpy(mem_txt + off, mask);\n            off+=strlen(mask);\n            mem_txt[off++] = '\\t';\n            if (strlen(mask) < 8)\n                mem_txt[off++] = '\\t';\n\n            /* Flags */\n            mem_txt[off++] = 'U';\n            if (r->netmask.addr == 0)\n                mem_txt[off++] = 'G';\n            mem_txt[off++] = '\\t';\n\n            /* Metric */\n            ul_to_str(r->metric, metric);\n            strcpy(mem_txt + off, metric);\n            off += strlen(metric);\n            mem_txt[off++] = '\\t';\n\n\n            /* Iface */\n            strcpy(mem_txt + off, r->link->dev->name);\n            off+=strlen(r->link->dev->name);\n\n            /* EOL */\n            mem_txt[off++] = '\\r';\n            mem_txt[off++] = '\\n';\n        }\n    }\n    cur_off = task_fd_get_off(fno);\n    if (off == cur_off) {\n        kfree(mem_txt);\n        sysfs_unlock();\n        mem_unlock();\n        return -1;\n    }\n    if (len > (off - cur_off)) {\n       len = off - cur_off;\n    }\n    memcpy(res, mem_txt + cur_off, len);\n    cur_off += len;\n    task_fd_set_off(fno,cur_off);\n    sysfs_unlock();\n    mem_unlock();\n    return len;\n}\n\nstatic int sock_getsockopt(int sd, int level, int optname, void *optval, unsigned int *optlen)\n{\n    struct frosted_inet_socket *s;\n    int ret;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    if (*optlen < sizeof(int)) {\n        ret = -EFAULT;\n        goto out;\n    }\n    s = fd_inet(sd);\n    if (!s) {\n        ret = -EINVAL;\n        goto out;\n    }\n    ret = pico_socket_getoption(s->sock, optname, optval);\n    if (ret < 0)\n        ret = 0 - pico_err;\n    else\n        *optlen = sizeof(int);\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_setsockopt(int sd, int level, int optname, void *optval, unsigned int optlen)\n{\n    struct frosted_inet_socket *s;\n    int ret;\n    if (optlen < sizeof(int))\n        return -EFAULT;\n\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    s = fd_inet(sd);\n    if (!s) {\n        ret = -EINVAL;\n    } else {\n        ret = pico_socket_setoption(s->sock, optname, optval);\n        if (ret < 0)\n            ret = 0 - pico_err;\n    }\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_getsockname(int sd, struct sockaddr *_addr, unsigned int *addrlen)\n{\n    struct pico_ip4 ip4a;\n    struct frosted_inet_socket *s;\n    struct sockaddr_in *addr = (struct sockaddr_in *)_addr;\n    int r;\n    uint16_t port, proto;\n    int ret = -1;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    s = fd_inet(sd);\n    if (!s) {\n        ret = -EINVAL;\n        goto out;\n    }\n\n    if (*addrlen < sizeof(struct sockaddr_in)) {\n        ret = -ENOBUFS;\n        goto out;\n    }\n    r = pico_socket_getname(s->sock, &ip4a, &port, &proto);\n    if (r < 0)  {\n        ret = 0 - pico_err;\n        goto out;\n    }\n\n    if (proto != PICO_PROTO_IPV4) {\n        ret = -ENOENT;\n        goto out;\n    }\n\n    memset(addr, 0, *addrlen);\n    *addrlen = sizeof(struct sockaddr_in);\n    addr->sin_family = AF_INET;\n    addr->sin_port = port;\n    addr->sin_addr.s_addr = ip4a.addr;\n    ret = 0;\nout:\n    mem_unlock();\n    return ret;\n}\n\nstatic int sock_getpeername(int sd, struct sockaddr *_addr, unsigned int *addrlen)\n{\n    struct pico_ip4 ip4a;\n    struct frosted_inet_socket *s;\n    struct sockaddr_in *addr = (struct sockaddr_in *)_addr;\n    int r;\n    uint16_t port, proto;\n    int ret = -1;\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n\n    s = fd_inet(sd);\n    if (!s) {\n        ret = -EINVAL;\n        goto out;\n    }\n\n    if (*addrlen < sizeof(struct sockaddr_in)) {\n        ret = -ENOBUFS;\n        goto out;\n    }\n    r = pico_socket_getpeername(s->sock, &ip4a, &port, &proto);\n    if (r < 0) {\n        ret = 0 - pico_err;\n        goto out;\n    }\n\n    if (proto != PICO_PROTO_IPV4) {\n        ret = -ENOTCONN;\n        goto out;\n    }\n\n    memset(addr, 0, *addrlen);\n    *addrlen = sizeof(struct sockaddr_in);\n    addr->sin_family = AF_INET;\n    addr->sin_port = port;\n    addr->sin_addr.s_addr = ip4a.addr;\n    ret = 0;\nout:\n    mem_unlock();\n    return ret;\n}\n\n\nstatic int sysfs_no_op(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    return -1;\n}\n\n\nvoid socket_in_init(void)\n{\n    mod_socket_in.family = FAMILY_INET;\n    strcpy(mod_socket_in.name,\"picotcp\");\n\n    mod_socket_in.ops.poll = sock_poll;\n    mod_socket_in.ops.close = sock_close;\n\n    mod_socket_in.ops.socket     = sock_socket;\n    mod_socket_in.ops.connect    = sock_connect;\n    mod_socket_in.ops.accept     = sock_accept;\n    mod_socket_in.ops.bind       = sock_bind;\n    mod_socket_in.ops.listen     = sock_listen;\n    mod_socket_in.ops.recvfrom   = sock_recvfrom;\n    mod_socket_in.ops.sendto     = sock_sendto;\n    mod_socket_in.ops.shutdown   = sock_shutdown;\n    mod_socket_in.ops.ioctl      = sock_ioctl;\n    mod_socket_in.ops.getsockopt   = sock_getsockopt;\n    mod_socket_in.ops.setsockopt   = sock_setsockopt;\n    mod_socket_in.ops.getsockname   = sock_getsockname;\n    mod_socket_in.ops.getpeername   = sock_getpeername;\n\n    register_module(&mod_socket_in);\n    register_addr_family(&mod_socket_in, FAMILY_INET);\n\n    /* Register /sys/net/dev */\n    sysfs_register(\"dev\", \"/sys/net\", sysfs_net_dev_read, NULL);\n\n    /* Register /sys/net/route */\n    sysfs_register(\"route\", \"/sys/net\", sysfs_net_route_list, NULL);\n\n}\n"
  },
  {
    "path": "kernel/drivers/socket_in.h",
    "content": "/*********************************************************************\nPicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved.\nSee LICENSE and COPYING for usage.\nDo not redistribute without a written permission by the Copyright\nholders.\n\nAuthor: Maxime Vincent, Daniele Lacamera\n*********************************************************************/\n#ifndef FROSTED_IN_SOCKETS_H_\n#define FROSTED_IN_SOCKETS_H_\n\n#include <stdint.h>\n#include <signal.h>\n\n#ifdef CONFIG_PICOTCP\n#include \"pico_defines.h\"\n#include \"pico_constants.h\"\n#include \"pico_config.h\"\n#include \"pico_stack.h\"\n#include \"pico_icmp4.h\"\n#include \"pico_stack.h\"\n#include \"pico_ipv4.h\"\n#include \"pico_ipv6.h\"\n#include \"pico_dns_client.h\"\n#include \"pico_socket.h\"\n#endif\n\n#define SOCKSIZE  16\n#define SOCKSIZE6 28\n\nstruct pico_bsd_endpoint;\nextern void   *picoLock;\nextern void   *pico_signal_tick;\n\n\ntypedef int socklen_t;\n#define AF_INET     (2)\n#define AF_INET6    (10)\n#define SOL_SOCKET (0x80)\n\n#define IP_MULTICAST_LOOP   (PICO_IP_MULTICAST_LOOP)\n#define IP_MULTICAST_TTL    (PICO_IP_MULTICAST_TTL)\n#define IP_MULTICAST_IF     (PICO_IP_MULTICAST_IF)\n#define IP_ADD_MEMBERSHIP   (PICO_IP_ADD_MEMBERSHIP)\n#define IP_DROP_MEMBERSHIP  (PICO_IP_DROP_MEMBERSHIP)\n#define SO_RCVBUF           (PICO_SOCKET_OPT_RCVBUF)\n#define SO_SNDBUF           (PICO_SOCKET_OPT_SNDBUF)\n#define TCP_NODELAY         (PICO_TCP_NODELAY)\n#define TCP_KEEPCNT         (PICO_SOCKET_OPT_KEEPCNT)\n#define TCP_KEEPIDLE        (PICO_SOCKET_OPT_KEEPIDLE)\n#define TCP_KEEPINTVL       (PICO_SOCKET_OPT_KEEPINTVL)\n#define TCP_LINGER          (PICO_SOCKET_OPT_LINGER)\n#define SO_ERROR            (4103)\n#define SO_REUSEADDR        (2)\n#define IPPROTO_ICMP        (1)\n#define IPPROTO_UDP         (17)\n#define sockopt_get_name(x) ((x))\n\n#define INET_ADDRSTRLEN    (16)\n#define INET6_ADDRSTRLEN   (46)\n\nstruct in_addr {\n    uint32_t s_addr;\n};\n\n#define INADDR_ANY ((uint32_t)0U)\n\nstruct in6_addr {\n    uint8_t s6_addr[16];\n};\n\nstruct __attribute__((packed)) sockaddr_in {\n    uint16_t sin_family;\n    uint16_t sin_port;\n    struct in_addr sin_addr;\n    uint8_t _pad[SOCKSIZE - 8];         \n};\n\n\nstruct __attribute__((packed)) sockaddr_in6 {\n    uint16_t sin6_family;\n    uint16_t sin6_port;\n    uint32_t sin6_flowinfo;\n    struct in6_addr sin6_addr;\n    uint32_t sin6_scope_id;\n};\n\nstruct __attribute__((packed)) sockaddr_storage {\n    uint16_t ss_family;\n    uint8_t  _pad[(SOCKSIZE6 - sizeof(uint16_t))];\n};\n\n/* getaddrinfo */\nstruct addrinfo {\n    int              ai_flags;\n    int              ai_family;\n    int              ai_socktype;\n    int              ai_protocol;\n    socklen_t        ai_addrlen;\n    char            *ai_canonname;\n    struct sockaddr *ai_addr;\n    struct addrinfo *ai_next;\n};\n\n\n/* hostent */\nstruct hostent {\n    char  *h_name;            /* official name of host */\n    char **h_aliases;         /* alias list */\n    int    h_addrtype;        /* host address type */\n    int    h_length;          /* length of address */\n    char **h_addr_list;       /* list of addresses */\n};\n#define h_addr h_addr_list[0] /* for backward compatibility */\n\n/* fd_set */\n#ifndef FD_SETSIZE\n#define FD_SETSIZE  64 /* 64 files max, 1 bit per file -> 64bits = 8 bytes */\n#endif\n\nstruct pico_fd_set_s {\n    uint8_t fds_bits[FD_SETSIZE/8];\n};\n\ntypedef struct pico_fd_set_s pico_fd_set;\n#ifndef fd_set\n#define fd_set pico_fd_set\n#endif\n\n//typedef void sigset_t;\n\n#define   PICO_FD_SET(n, p)   ((p)->fds_bits[(n)/8] |=  (1u << ((n) % 8)))\n#define   PICO_FD_CLR(n, p)   ((p)->fds_bits[(n)/8] &= ~(1u << ((n) % 8)))\n#define   PICO_FD_ISSET(n, p) ((p)->fds_bits[(n)/8] &   (1u << ((n) % 8)))\n#define   PICO_FD_ZERO(p)     do{memset((p)->fds_bits, 0, sizeof(struct pico_fd_set_s));}while(0)\n\n/* Not socket related */\n#ifndef __time_t_defined\ntypedef pico_time time_t;\n#define __time_t_defined\n#endif\n\n#if !defined _TIME_H && !defined _TIMEVAL_DEFINED && !defined _STRUCT_TIMEVAL\nstruct timeval {\n    time_t tv_sec;\n    time_t tv_usec;\n};\n\n#if !defined __timespec_defined && !defined _SYS__TIMESPEC_H_\nstruct timespec {\n    long tv_sec;\n    long tv_nsec;\n};\n#endif\n\nstruct timezone {\n    int tz_minuteswest;     /* minutes west of Greenwich */\n    int tz_dsttime;         /* type of DST correction */\n};\n#define _TIMEVAL_DEFINED\n#endif\n\n#ifndef SO_REUSEPORT\n    #define SO_REUSEPORT    (15)\n#endif\n\n\n#ifndef O_NONBLOCK\n    #define O_NONBLOCK  0x4000\n#endif\n\n#ifndef _SYS_POLL_H\n    #define POLLIN      0x001       /* There is data to read.  */\n    #define POLLPRI     0x002       /* There is urgent data to read.  */\n    #define POLLOUT     0x004       /* Writing now will not block.  */\n    #define POLLRDNORM 0x040       /* Normal data may be read.  */\n    #define POLLRDBAND 0x080       /* Priority data may be read.  */\n    #define POLLWRNORM 0x100       /* Writing now will not block.  */\n    #define POLLWRBAND 0x200       /* Priority data may be written.  */\n    \n    #define POLLMSG    0x400\n    #define POLLREMOVE 0x1000\n    #define POLLRDHUP  0x2000\n    \n    #define POLLERR     0x008       /* Error condition.  */\n    #define POLLHUP     0x010       /* Hung up.  */\n    #define POLLNVAL    0x020       /* Invalid polling request.  */\n    \n    typedef unsigned long int nfds_t;\n    \n    struct pollfd {\n        int fd;\n        uint16_t events;\n        uint16_t revents;\n    };\n#endif\n\nvoid pico_lock(void);\nvoid pico_unlock(void);\nvoid socket_in_init(void);\n\n#endif /* PICO_BSD_SOCKETS_H_ */\n"
  },
  {
    "path": "kernel/drivers/socket_un.c",
    "content": "#include \"frosted.h\"\n#include <string.h>\n\nstatic struct module mod_socket_un;\nstruct fnode FNO_SOCKUN_STUB = {\n    .owner = &mod_socket_un\n};\n\nstatic int sock_check_fd(int fd, struct fnode **fno)\n{\n    *fno = task_filedesc_get(fd);\n    \n    if (!fno)\n        return -1;\n\n    if (fd < 0)\n        return -1;\n    if ((*fno)->owner != &mod_socket_un)\n        return -1;\n\n    return 0;\n}\n\nstatic int sock_poll(int fd, uint16_t events, uint16_t *revents)\n{\n    *revents = events;\n    return 1;\n}\n\n\nstatic int sock_close(int fd)\n{\n    struct fnode *fno;\n    if (sock_check_fd(fd, &fno))\n        return -1;\n    kprintf(\"## Closed UNIX socket!\\n\");\n    /* TODO */\n    return 0;\n}\n\nint sock_socket(int domain, int type, int protocol)\n{\n    int fd = -1;\n    kprintf(\"## Opened UNIX socket!\\n\");\n    fd = task_filedesc_add(&FNO_SOCKUN_STUB);\n    return fd;\n}\nint sock_recvfrom(int fd, void *buf, unsigned int len, int flags, struct sockaddr *addr, unsigned int *addrlen)\n{\n    return -1;\n}\n\nint sock_sendto(int fd, const void *buf, unsigned int len, int flags, struct sockaddr *addr, unsigned int addrlen)\n{\n    return -1;\n}\nint sock_bind(int fd, struct sockaddr *addr, unsigned int addrlen)\n{\n    return -1;\n}\n\nint sock_accept(int fd, struct sockaddr *addr, unsigned int *addrlen)\n{\n    return -1;\n}\n\nint sock_connect(int fd, struct sockaddr *addr, unsigned int addrlen)\n{\n    return -1;\n}\n\nint sock_listen(int fd, int backlog)\n{\n    return -1;\n}\n\nint sock_shutdown(int fd, uint16_t how)\n{\n    return -1;\n}\n\n\nvoid socket_un_init(void)\n{\n    mod_socket_un.family = FAMILY_UNIX;\n    strcpy(mod_socket_un.name,\"un\");\n    mod_socket_un.ops.poll = sock_poll;\n    mod_socket_un.ops.close = sock_close;\n\n    mod_socket_un.ops.socket     = sock_socket;\n    mod_socket_un.ops.connect    = sock_connect;\n    mod_socket_un.ops.accept     = sock_accept;\n    mod_socket_un.ops.bind       = sock_bind;\n    mod_socket_un.ops.listen     = sock_listen;\n    mod_socket_un.ops.recvfrom   = sock_recvfrom;\n    mod_socket_un.ops.sendto     = sock_sendto;\n    mod_socket_un.ops.shutdown   = sock_shutdown;\n\n    register_module(&mod_socket_un);\n    register_addr_family(&mod_socket_un, FAMILY_UNIX);\n}\n\n\n\n"
  },
  {
    "path": "kernel/drivers/spi.h",
    "content": "#ifndef INC_SPI\n#define INC_SPI\n#include \"dma.h\"\n#include \"gpio.h\"\n\nstruct spi_config {\n    int idx;\n    uint32_t base;\n    uint32_t irq;\n    uint32_t rcc;\n    uint32_t baudrate;\n    uint8_t polarity;\n    uint8_t phase;\n    uint8_t rx_only;\n    uint8_t bidir_mode;\n    uint16_t dff_16;\n    uint8_t enable_software_slave_management;\n    uint8_t send_msb_first;\n    \n    /* DMA Config */\n    uint32_t dma_rcc;\n    struct dma_config tx_dma;\n    struct dma_config rx_dma;\n\n    /* Pin muxing */\n    struct gpio_config pio_sck;\n    struct gpio_config pio_miso;\n    struct gpio_config pio_mosi;\n    struct gpio_config pio_nss;\n};\n\nstruct spi_slave {\n    uint8_t bus;\n    void (*isr)(struct spi_slave *);\n    void *priv;\n};\n\nint devspi_create(const struct spi_config *spi_config);\nint devspi_xfer(struct spi_slave *spi, const char *obuf, char *ibuf, unsigned int len);\n\n#endif\n\n"
  },
  {
    "path": "kernel/drivers/stm32_dma.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"cirbuf.h\"\n#include <unicore-mx/stm32/dma.h>\n\n#include \"dma.h\"\n\n\nvoid init_dma(const struct dma_config * dma, uint32_t ptr, uint32_t len)\n{\n    dma_stream_reset(dma->base, dma->stream);\n\n    dma_set_transfer_mode(dma->base, dma->stream, dma->dirn);\n    dma_set_priority(dma->base, dma->stream, dma->prio);\n\n    dma_set_peripheral_address(dma->base, dma->stream, dma->paddr);\n    dma_disable_peripheral_increment_mode(dma->base, dma->stream);\n    dma_set_peripheral_size(dma->base, dma->stream, dma->psize);\n\n    dma_enable_memory_increment_mode(dma->base, dma->stream);\n    dma_set_memory_size(dma->base, dma->stream, dma->msize);\n\n    dma_enable_direct_mode(dma->base, dma->stream);\n    dma_set_dma_flow_control(dma->base, dma->stream);\n\n    dma_channel_select(dma->base,dma->stream,dma->channel);\n\n    dma_set_memory_address(dma->base, dma->stream, ptr);\n    dma_set_number_of_data(dma->base, dma->stream, len);\n    dma_enable_stream(dma->base, dma->stream);\n}\n"
  },
  {
    "path": "kernel/drivers/stm32_eth.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Maxime Vincent\n *\n */\n\n#include <stdint.h>\n#include \"frosted.h\"\n#include \"gpio.h\"\n#include \"eth.h\"\n\n#include <pico_stack.h>\n#include <pico_device.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/syscfg.h>\n#include <unicore-mx/ethernet/mac.h>\n#include <unicore-mx/ethernet/phy.h>\n#include \"unicore-mx/cm3/nvic.h\"\n\n#define dbg(...)\n\n#define ETH_MAX_FRAME    (1524)                 /* Round to multiple of 4 bytes! */\n#define ETH_IRQ_PRIO        (1)\n\n/* FIXME: Put in board config */\n#define BOARD_PHY_RMII                          /* Whether the board uses RMII or MII */\n#define BOARD_phy_addr      PHY_LAN8710A_ID     /* The PHY ID to be detected on one of the PHY addresses */\n\n/* Some known PHY-identifiers */\n#define PHY_KSZ8021_ID    0x00221556\n#define PHY_KS8721_ID     0x00221610\n#define PHY_DP83848I_ID   0x20005C90\n#define PHY_LAN8710A_ID   0x0007C0F1\n#define PHY_DM9161_ID     0x0181B8A0\n#define PHY_AM79C875_ID   0x00225540\n#define PHY_STE101P_ID    0x00061C50\n\nstruct dev_eth {\n    struct pico_device dev;\n    uint32_t rx_prod;\n    uint32_t rx_cons;\n    uint8_t mac_addr[6];\n    uint8_t phy_addr;\n};\n\nstatic struct module mod_eth = {\n    .family = FAMILY_DEV,\n    .name = \"ethernet\",\n};\n\nstatic struct dev_eth * dev_eth_stm = NULL;\nstatic uint8_t eth_rx_buf[ETH_MAX_FRAME];\n\n#ifdef STM32F4\nstatic const uint8_t default_mac[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54};\n#else\nstatic const uint8_t default_mac[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x57};\n#endif\n\nstatic uint32_t eth_smi_get_phy_divider(void)\n{\n    uint32_t hclk = rcc_ahb_frequency;\n\n#if defined(STM32F4) || defined(STM32F7)\n    /* CSR Clock above 200 MHz */\n    if (hclk >= 200000000)\n        return ETH_MACMIIAR_CR_HCLK_DIV_124;\n\n    /* CSR Clock between 150-168 MHz */\n    if (hclk >= 150000000)\n        return ETH_MACMIIAR_CR_HCLK_DIV_102;\n#endif\n\n    /* CSR Clock between 100-150 MHz */\n    if (hclk >= 100000000)\n        return ETH_MACMIIAR_CR_HCLK_DIV_62;\n\n    /* CSR Clock between 60-100 MHz */\n    if (hclk >= 60000000)\n        return ETH_MACMIIAR_CR_HCLK_DIV_42;\n\n    /* CSR Clock between 35-60 MHz */\n    if (hclk >= 35000000)\n        return ETH_MACMIIAR_CR_HCLK_DIV_26;\n\n    /* CSR Clock between 20-35 MHz */\n    if (hclk >= 20000000)\n        return ETH_MACMIIAR_CR_HCLK_DIV_16;\n\n    dbg(\"STM32_HCLK below minimum frequency for ETH operations (20MHz)\\n\");\n    return 0;\n}\n\nstatic int8_t find_phy(uint32_t clk_div)\n{\n    uint32_t phy;\n\n    for (phy = 0; phy < 31; phy++)\n    {\n        ETH_MACMIIDR = (phy << 6) | clk_div;\n        if ( (eth_smi_read(phy, PHY_REG_ID1) == (BOARD_phy_addr >> 16)) &&\n            ((eth_smi_read(phy, PHY_REG_ID2) & 0xFFF0) == (BOARD_phy_addr & 0xFFF0)) )\n            return (int8_t)phy;\n    }\n    /* PHY not detected */\n    return -1;\n}\n\n\nstatic int stm_eth_poll(struct pico_device *dev, int loop_score)\n{\n    uint32_t rx_len = 0;\n    /* Possible optimization: \n     * add eth_rx_peek, then dynamically alloc + zerocopy \n     */\n    while ((loop_score > 0) && eth_rx(eth_rx_buf, &rx_len, ETH_MAX_FRAME))\n    {\n        pico_stack_recv(dev, eth_rx_buf, rx_len);\n        rx_len = 0;\n        loop_score--;\n    }\n    return loop_score;\n}\n\n\nstatic int stm_eth_send(struct pico_device *dev, void * buf, int len)\n{\n    if (len > ETH_MAX_FRAME)\n        len = ETH_MAX_FRAME;\n    if (eth_tx(buf, len))\n        return len;\n    else\n        return 0;\n}\n\n/* link state -> 0 == DOWN, 1 == UP */\nstatic int stm_eth_link_state(struct pico_device *dev)\n{\n    struct dev_eth *stm = (struct dev_eth *)dev;\n    /* test link state */\n    if (phy_link_isup(stm->phy_addr))\n        return 1;\n    else\n        return 0;\n}\n\n/**\n * Description: Low level MAC initialization.\n * Parameters:  phy_addr    Pointer a phy_addr variable\n *              clk_div     Phy Clock Divider\n */\nstatic int mac_init(uint8_t * phy_addr, uint32_t clk_div)\n{\n    int8_t phy_detect;\n\n    /* Enable SYSCFG clock */\n    rcc_periph_clock_enable(RCC_SYSCFG);\n\n    /* MAC clocks stopped to configure RMII .*/\n    rcc_periph_clock_disable(RCC_ETHMAC);\n    rcc_periph_clock_disable(RCC_ETHMACTX);\n    rcc_periph_clock_disable(RCC_ETHMACRX);\n\n    /* XXX FIXME */\n    #define SYSCFG_PMC_MII_RMII_SEL         ((uint32_t)0x00800000) /*!<Ethernet PHY interface selection */\n    #if defined(BOARD_PHY_RMII)\n      SYSCFG_PMC |= SYSCFG_PMC_MII_RMII_SEL;\n    #else\n      SYSCFG_PMC &= ~SYSCFG_PMC_MII_RMII_SEL;\n    #endif\n\n    /* Enable RCC clocks: Eth, GPIO */\n    rcc_periph_clock_enable(RCC_ETHMAC);\n    rcc_periph_clock_enable(RCC_ETHMACTX);\n    rcc_periph_clock_enable(RCC_ETHMACRX);\n\n    rcc_periph_clock_enable(RCC_GPIOA);\n    rcc_periph_clock_enable(RCC_GPIOB);\n    rcc_periph_clock_enable(RCC_GPIOC);\n    rcc_periph_clock_enable(RCC_GPIOE);\n\n    rcc_osc_on(RCC_PLL);\n    rcc_wait_for_osc_ready(RCC_PLL);\n\n    /* Reset of the MAC core.*/\n    rcc_periph_reset_pulse(RST_ETHMAC);\n\n    /* MAC clocks temporary activation.*/\n    rcc_periph_clock_enable(RCC_ETHMAC);\n    rcc_periph_clock_enable(RCC_ETHMACTX);\n    rcc_periph_clock_enable(RCC_ETHMACRX);\n\n    /* PHY address setup.*/\n    phy_detect = find_phy(clk_div);\n    *phy_addr = (uint8_t)phy_detect;\n    if (phy_detect == -1)   /* Detect PHY address */\n        return -1;          /* PHY not found */\n\n    /* PHY Soft Reset */\n    eth_smi_write(*phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET);\n    while (eth_smi_read(*phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET) {};\n\n    /* ETH DMA Soft Reset */\n    ETH_DMABMR |= ETH_DMABMR_SR;\n    while(ETH_DMABMR & ETH_DMABMR_SR) {};\n\n    return 0;\n}\n\nstatic void pico_eth_start_deferred(uint32_t t, void *arg)\n{\n    int8_t phy_addr;\n    uint8_t * descriptors;\n    uint32_t clk_div = eth_smi_get_phy_divider();\n    const char ipstr[] = CONFIG_ETH_DEFAULT_IP;\n    const char nmstr[] = CONFIG_ETH_DEFAULT_NM;\n    const char gwstr[] = CONFIG_ETH_DEFAULT_GW;\n    struct pico_ip4 default_ip, default_nm, default_gw, zero;\n    zero.addr = 0U;\n\n    (void)arg;\n    (void)t;\n    pico_string_to_ipv4(ipstr, &default_ip.addr);\n    pico_string_to_ipv4(nmstr, &default_nm.addr);\n    pico_string_to_ipv4(gwstr, &default_gw.addr);\n\n\n    dev_eth_stm = kalloc(sizeof(struct dev_eth));\n    if (!dev_eth_stm)\n        return;\n    memset(dev_eth_stm, 0, sizeof(struct dev_eth));\n    mac_init(&dev_eth_stm->phy_addr, clk_div);\n\n    /* DMA soft-reset */\n    ETH_DMABMR |= ETH_DMABMR_SR;\n    while(ETH_DMABMR & ETH_DMABMR_SR) {};\n\n    eth_init(phy_addr, clk_div); /* does a phy_reset */\n    eth_set_mac((uint8_t*)default_mac);\n\n    /* Initialize descriptors */\n    /* sizes must be multiple of 4 bytes! buffer must be 4 byte aligned */\n    descriptors = kalloc(2 * 2 * ETH_MAX_FRAME + 2 * 16); /* size of buffers + size of descriptors */\n    if (!descriptors)\n        return;\n    eth_desc_init(descriptors, 2, 2, ETH_MAX_FRAME, ETH_MAX_FRAME, false);\n\n    /* set pico function pointers */\n    dev_eth_stm->dev.poll = stm_eth_poll;\n    dev_eth_stm->dev.send = stm_eth_send;\n    dev_eth_stm->dev.link_state = stm_eth_link_state;\n\n    if (pico_device_init(&dev_eth_stm->dev,\"eth0\", default_mac) < 0) {\n        kfree(dev_eth_stm);\n        return;\n    }\n    /* Set address/netmask */\n    pico_ipv4_link_add(&dev_eth_stm->dev, default_ip, default_nm);\n    /* Set default gateway */\n    if (default_gw.addr)\n        pico_ipv4_route_add(zero, zero, default_gw, 1, NULL);\n\n    /* Enabling required interrupt sources.*/\n    eth_irq_ack_pending(ETH_DMASR);\n    eth_irq_disable(0xFFFF); /* Disable all */\n    eth_irq_enable(ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE);\n    nvic_set_priority(NVIC_ETH_IRQ, ETH_IRQ_PRIO);\n    nvic_enable_irq(NVIC_ETH_IRQ);\n\n    eth_start();\n}\n\n\n\n/* HW initialization */\nstatic struct eth_config init_defer_eth_config;\n\nstatic void ethernet_init_deferred(uint32_t t, void *arg)\n{\n    unsigned int i;\n    (void)t;\n    struct eth_config *conf = (struct eth_config *)arg;\n    /* Create MII pins */\n    for (i = 0; i < conf->n_pio_mii; i++)\n        gpio_create(&mod_eth, &(conf->pio_mii[i]));\n    /* Create PHY reset pin, if needed */\n    if (conf->has_phy_reset) {\n        gpio_create(&mod_eth, &conf->pio_phy_reset);\n        /* Reset PHY */\n        gpio_clear(conf->pio_phy_reset.base, conf->pio_phy_reset.pin);\n        gpio_set(conf->pio_phy_reset.base, conf->pio_phy_reset.pin);\n    }\n}\n\nint pico_eth_start(void) {\n    ktimer_add(100, ethernet_init_deferred, &init_defer_eth_config);\n    ktimer_add(300, pico_eth_start_deferred, NULL);\n    return 0;\n}\n\nint ethernet_init(const struct eth_config *conf)\n{\n    memcpy(&init_defer_eth_config, conf, sizeof(struct eth_config));\n    return 0;\n}\n\nvoid eth_isr(void)\n{\n    uint32_t bits = ETH_DMASR;\n    /* Clear all bits */\n    eth_irq_ack_pending(ETH_DMASR);\n    if (bits & ETH_DMASR_RS)\n    {\n        /* Receive Status bit set */\n        dev_eth_stm->rx_prod++;\n    }\n}\n\n"
  },
  {
    "path": "kernel/drivers/stm32_i2c.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include <unicore-mx/cm3/nvic.h>\n\n#include <unicore-mx/stm32/dma.h>\n#include \"unicore-mx/stm32/i2c.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/gpio.h>\n#include \"device.h\"\n#include <stdint.h>\n#include \"cirbuf.h\"\n#include \"dma.h\"\n#include \"i2c.h\"\n#include \"locks.h\"\n\n/* Dummy module, for gpio claiming only. */\nstatic struct module mod_i2c = {\n    .family = FAMILY_DEV,\n    .name = \"i2c\"\n};\n\nenum i2c_state\n{\n    I2C_STATE_READY,\n    I2C_STATE_ADDRESS,\n    I2C_STATE_REGISTER,\n    I2C_STATE_READ,\n    I2C_STATE_READ_ADDRESS,\n    I2C_STATE_READ_DATA,\n    I2C_STATE_DATA,\n    I2C_STATE_DMA_COMPLETE,\n    I2C_STATE_BTF,\n    I2C_STATE_ERROR,\n    I2C_STATE_MAX\n};\n\nenum i2c_ev\n{\n    I2C_EV_START,\n    I2C_EV_TIMEOUT,\n    I2C_EV_MASTER_MODE_SELECT,\n    I2C_EV_MASTER_MODE_ADDRESS10,\n    I2C_EV_MASTER_TRANSMITTER_MODE_SELECTED,\n    I2C_EV_MASTER_RECEIVER_MODE_SELECTED,\n    I2C_EV_DMA_COMPLETE_TX,\n    I2C_EV_DMA_COMPLETE_RX,\n    I2C_EV_BTF,\n    I2C_EV_TXE,\n    I2C_EV_MAX\n};\n\nstruct dev_i2c {\n    struct device * dev;\n    uint32_t base;\n    void (*isr)(struct i2c_slave *sl);\n    struct i2c_slave *sl;\n    uint32_t ev_irq;\n    uint32_t er_irq;\n    uint8_t slv_register;\n    const struct dma_config * tx_dma_config;\n    const struct dma_config * rx_dma_config;\n    mutex_t *mutex;\n\n    uint8_t dirn;\n    uint8_t kthread_transfer_complete;\n    volatile enum i2c_state state;\n};\n\n#define MAX_I2CS 4\n\nstatic struct dev_i2c *DEV_I2C[MAX_I2CS] = { };\n\nstatic void state_machine(struct dev_i2c *i2c, enum i2c_ev ev);\n\n/*****************************\n    MASTER_MODE_SELECT                                   SR2: BUSY|MSL              SR1: SB\n    MASTER_MODE_ADDRESS10                           SR2: BUSY|MSL               SR1: ADD10\n    MASTER_TRANSMITTER_MODE_SELECTED     SR2: BUSY|MSL|TRA      SR1: TXE|ADDR\n    MASTER_RECEIVER_MODE_SELECTED           SR2: BUSY|MSL               SR1: ADDR\n*****************************/\nstatic void i2c_ev(struct dev_i2c * i2c)\n{\n    uint32_t sr1 = I2C_SR1(i2c->base);\n    uint32_t sr2 = I2C_SR2(i2c->base);\n    /* MASTER_MODE_SELECT */\n    if ((sr1 & (I2C_SR1_SB)) == (I2C_SR1_SB))\n        state_machine(i2c, I2C_EV_MASTER_MODE_SELECT);\n    /* MASTER_MODE_ADDRESS10 */\n    else if((((sr1 & (I2C_SR1_ADD10)) == (I2C_SR1_ADD10)) &&\n            (sr2 & (I2C_SR2_BUSY | I2C_SR2_MSL)) == (I2C_SR2_BUSY | I2C_SR2_MSL))   )\n        state_machine(i2c, I2C_EV_MASTER_MODE_ADDRESS10);\n    /* MASTER_TRANSMITTER_MODE_SELECTED */\n    else if((((sr1 & (I2C_SR1_TxE | I2C_SR1_ADDR)) == (I2C_SR1_TxE | I2C_SR1_ADDR)) &&\n            (sr2 & (I2C_SR2_BUSY | I2C_SR2_MSL | I2C_SR2_TRA)) == (I2C_SR2_BUSY | I2C_SR2_MSL | I2C_SR2_TRA))   )\n        state_machine(i2c, I2C_EV_MASTER_TRANSMITTER_MODE_SELECTED);\n    /* MASTER_RECEIVER_MODE_SELECTED */\n    else if(//((sr1 & (I2C_SR1_ADDR)) == (I2C_SR1_ADDR)) &&\n            ((sr2 &(I2C_SR2_BUSY | I2C_SR2_MSL)) == (I2C_SR2_BUSY | I2C_SR2_MSL))   )\n        state_machine(i2c, I2C_EV_MASTER_RECEIVER_MODE_SELECTED);\n\n    /* TxE / BTF */\n    if(    (sr1 & (I2C_SR1_TxE)) == (I2C_SR1_TxE)   )\n        state_machine(i2c, I2C_EV_TXE);\n    if(    (sr1 & (I2C_SR1_BTF)) == (I2C_SR1_BTF)   )\n        state_machine(i2c, I2C_EV_BTF);\n\n}\n\nstatic void restart_state_machine(struct dev_i2c *i2c);\n\n/*****************************\n    BERR             I2C_SR1_BERR\n    AF                  I2C_SR1_AF\n    OVR               I2C_SR1_OVR\n    PECERR          I2C_SR1_PECERR\n    TIMEOUT        I2C_SR1_TIMEOUT\n    SMBALERT    I2C_SR1_SMBALERT\n*****************************/\nstatic void i2c_er(struct dev_i2c * i2c)\n{\n    volatile uint32_t er;\n    if (!i2c)\n        return;\n    er = I2C_SR1(i2c->base);\n    if(er & (I2C_SR1_TIMEOUT) == (I2C_SR1_TIMEOUT))\n        state_machine(i2c, I2C_EV_TIMEOUT);\n    else {\n        i2c_send_stop(i2c->base);\n        i2c_peripheral_disable(i2c->base);\n        restart_state_machine(i2c);\n        i2c->kthread_transfer_complete++;\n    }\n}\n\nstatic void i2c_rx_dma_complete(struct dev_i2c * i2c)\n{\n    if (!i2c)\n        return;\n    state_machine(i2c, I2C_EV_DMA_COMPLETE_RX);\n}\nstatic void i2c_tx_dma_complete(struct dev_i2c * i2c)\n{\n    if (!i2c)\n        return;\n    state_machine(i2c, I2C_EV_DMA_COMPLETE_TX);\n}\n\n#ifdef CONFIG_I2C1\nvoid i2c1_ev_isr(void)\n{\n    i2c_ev(DEV_I2C[1]);\n}\nvoid i2c1_er_isr(void)\n{\n    i2c_er(DEV_I2C[1]);\n}\nvoid dma1_stream5_isr()\n{\n    dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_LISR_TCIF0);\n    i2c_rx_dma_complete(DEV_I2C[1]);\n}\nvoid dma1_stream6_isr()\n{\n    dma_clear_interrupt_flags(DMA1, DMA_STREAM6, DMA_LISR_TCIF0);\n    i2c_tx_dma_complete(DEV_I2C[1]);\n}\n#endif\n\n#ifdef CONFIG_I2C3\nvoid i2c3_ev_isr(void)\n{\n    i2c_ev(DEV_I2C[3]);\n}\nvoid i2c3_er_isr(void)\n{\n    i2c_er(DEV_I2C[3]);\n}\nvoid dma1_stream2_isr()\n{\n    dma_clear_interrupt_flags(DMA1, DMA_STREAM2, DMA_LISR_TCIF0);\n    i2c_rx_dma_complete(DEV_I2C[3]);\n}\nvoid dma1_stream4_isr()\n{\n    dma_clear_interrupt_flags(DMA1, DMA_STREAM4, DMA_LISR_TCIF0);\n    i2c_tx_dma_complete(DEV_I2C[3]);\n}\n#endif\n\n\nstatic void restart_state_machine(struct dev_i2c *i2c)\n{\n    mutex_unlock(i2c->mutex);\n    i2c_peripheral_enable(i2c->base);\n    i2c->state = I2C_STATE_READY;\n}\n\nstatic void state_machine(struct dev_i2c *i2c, enum i2c_ev ev)\n{\n    volatile uint16_t cr1;\n    volatile uint16_t cr2;\n\n\n    switch(i2c->state)\n    {\n        case I2C_STATE_READY:\n            if (ev == I2C_EV_START) {\n                i2c_peripheral_enable(i2c->base);\n                i2c_enable_interrupt(i2c->base, I2C_CR2_ITEVTEN | I2C_CR2_ITERREN);\n                i2c->state = I2C_STATE_ADDRESS;\n                i2c_set_dma_last_transfer(i2c->base);\n                i2c_send_start(i2c->base);\n            }\n            break;\n\n        case I2C_STATE_ADDRESS:\n            switch(ev)\n            {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_MASTER_MODE_SELECT:\n                    i2c->state = I2C_STATE_REGISTER;\n                    i2c_send_7bit_address(i2c->base, i2c->sl->address >> 1, 0);\n                    break;\n            }\n            break;\n\n        case I2C_STATE_REGISTER:\n            switch(ev)\n                {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_MASTER_TRANSMITTER_MODE_SELECTED:\n                case I2C_EV_MASTER_RECEIVER_MODE_SELECTED:\n                    if(i2c->dirn)\n                    {\n                        i2c->state = I2C_STATE_READ;\n                    }\n                    else\n                    {\n                        i2c->state = I2C_STATE_DATA;\n                    }\n                    I2C_DR(i2c->base) = i2c->slv_register;\n                    break;\n                }\n            break;\n\n        case I2C_STATE_READ:\n            switch(ev)\n            {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_TXE:\n                    i2c->state = I2C_STATE_READ_ADDRESS;\n                    i2c_send_start(i2c->base);\n                    break;\n            }\n            break;\n\n        case I2C_STATE_READ_ADDRESS:\n            switch(ev)\n            {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_MASTER_MODE_SELECT:\n                    i2c->state = I2C_STATE_READ_DATA;\n                    i2c_send_7bit_address(i2c->base, i2c->sl->address >> 1, 1);\n                    break;\n            }\n            break;\n\n        case I2C_STATE_READ_DATA:\n            switch(ev)\n            {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_MASTER_RECEIVER_MODE_SELECTED:\n                    i2c_peripheral_enable(i2c->base);\n                    i2c->state = I2C_STATE_DMA_COMPLETE;\n                    i2c_enable_dma(i2c->base);\n                    break;\n            }\n            break;\n\n        case I2C_STATE_DATA:\n            switch(ev)\n            {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_TXE:\n                    i2c->state = I2C_STATE_DMA_COMPLETE;\n                    i2c_enable_dma(i2c->base);\n                    break;\n            }\n            break;\n\n        case I2C_STATE_DMA_COMPLETE:\n            switch(ev)\n            {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_DMA_COMPLETE_RX:\n                    i2c->kthread_transfer_complete++;\n                    i2c_disable_dma(i2c->base);\n                    i2c_send_stop(i2c->base);\n                    i2c_peripheral_disable(i2c->base);\n                    i2c->isr(i2c->sl);\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_DMA_COMPLETE_TX:\n                    i2c_disable_dma(i2c->base);\n                    i2c->state = I2C_STATE_BTF;\n                    break;\n            }\n            break;\n\n        case I2C_STATE_BTF:\n            switch(ev)\n            {\n                case  I2C_EV_TIMEOUT:\n                    restart_state_machine(i2c);\n                    break;\n                case I2C_EV_TXE:\n                case I2C_EV_BTF:\n                    i2c->kthread_transfer_complete++;\n                    i2c_disable_dma(i2c->base);\n                    i2c_send_stop(i2c->base);\n                    i2c_peripheral_disable(i2c->base);\n                    i2c->isr(i2c->sl);\n                    restart_state_machine(i2c);\n                    break;\n            }\n            break;\n        case I2C_STATE_ERROR:\n            restart_state_machine(i2c);\n            break;\n    }\n}\n\nstatic void isr_kthread(struct i2c_slave *sl)\n{\n    struct dev_i2c *i2c;\n    i2c = DEV_I2C[sl->bus];\n    if (!i2c)\n        return;\n}\n\nint i2c_kthread_read(struct i2c_slave *sl, uint8_t reg, uint8_t *buf, uint32_t len)\n{\n    struct dev_i2c *i2c;\n\n    if (len <= 0)\n        return len;\n\n    i2c = DEV_I2C[sl->bus];\n    if (!i2c)\n        return -ENOENT;\n\n    mutex_lock(i2c->mutex);\n    i2c->dirn = 1;\n    i2c->slv_register = reg;\n    i2c->isr = isr_kthread;\n    i2c->sl = sl;\n    i2c->kthread_transfer_complete = 0;\n    init_dma(i2c->rx_dma_config, (uint32_t)buf, len);\n    dma_enable_transfer_complete_interrupt(i2c->rx_dma_config->base, i2c->rx_dma_config->stream);\n    nvic_set_priority(i2c->rx_dma_config->irq, 1);\n    nvic_enable_irq(i2c->rx_dma_config->irq);\n    state_machine(i2c, I2C_EV_START);\n    while(i2c->kthread_transfer_complete == 0)\n       kthread_yield();\n    kthread_sleep_ms(10);\n    return len;\n}\n\nint i2c_kthread_write(struct i2c_slave *sl, uint8_t reg, const uint8_t *buf, uint32_t len)\n{\n    struct dev_i2c *i2c;\n\n    if (len <= 0)\n        return len;\n\n    i2c = DEV_I2C[sl->bus];\n    if (!i2c)\n        return -ENOENT;\n\n    mutex_lock(i2c->mutex);\n    i2c->dirn = 0;\n    i2c->slv_register = reg;\n    i2c->isr = isr_kthread;\n    i2c->sl = sl;\n    init_dma(i2c->tx_dma_config, (uint32_t)buf, len);\n    dma_enable_transfer_complete_interrupt(i2c->tx_dma_config->base, i2c->tx_dma_config->stream);\n    nvic_set_priority(i2c->tx_dma_config->irq, 1);\n    nvic_enable_irq(i2c->tx_dma_config->irq);\n    state_machine(i2c, I2C_EV_START);\n    while(i2c->kthread_transfer_complete == 0)\n       kthread_yield();\n    kthread_sleep_ms(10);\n    return len;\n}\n\nint i2c_init_read(struct i2c_slave *sl, uint8_t reg, uint8_t *buf, uint32_t len)\n{\n    struct dev_i2c *i2c;\n\n    if (len <= 0)\n        return len;\n\n    i2c = DEV_I2C[sl->bus];\n    if (!i2c)\n        return -ENOENT;\n\n    if (mutex_trylock(i2c->mutex) < 0)\n        return -EBUSY;\n\n    i2c->dirn = 1;\n    i2c->slv_register = reg;\n    i2c->isr = sl->isr_rx;\n    i2c->sl = sl;\n    init_dma(i2c->rx_dma_config, (uint32_t)buf, len);\n    dma_enable_transfer_complete_interrupt(i2c->rx_dma_config->base, i2c->rx_dma_config->stream);\n    nvic_set_priority(i2c->rx_dma_config->irq, 1);\n    nvic_enable_irq(i2c->rx_dma_config->irq);\n    state_machine(i2c, I2C_EV_START);\n    return 0;\n}\n\nint i2c_init_write(struct i2c_slave *sl, uint8_t reg, const uint8_t *buf, uint32_t len)\n{\n    struct dev_i2c *i2c;\n\n    if (len <= 0)\n        return len;\n\n    i2c = DEV_I2C[sl->bus];\n    if (!i2c)\n        return -ENOENT;\n\n    if (mutex_trylock(i2c->mutex) < 0)\n        return -EBUSY;\n\n    i2c->dirn = 0;\n    i2c->slv_register = reg;\n    i2c->isr = sl->isr_tx;\n    i2c->sl = sl;\n    init_dma(i2c->tx_dma_config, (uint32_t)buf, len);\n    dma_enable_transfer_complete_interrupt(i2c->tx_dma_config->base, i2c->tx_dma_config->stream);\n    nvic_set_priority(i2c->tx_dma_config->irq, 1);\n    nvic_enable_irq(i2c->tx_dma_config->irq);\n    state_machine(i2c, I2C_EV_START);\n    return 0;\n}\n\nstatic int i2c_fno_init(const struct i2c_config *conf, struct dev_i2c *i)\n{\n    struct fnode *devfs = fno_search(\"/dev\");\n    char name[5] = \"i2cX\";\n    if (!devfs)\n        return -EFAULT;\n\n    name[3] = '0' + conf->idx;\n\n}\n\nint i2c_create(const struct i2c_config *conf)\n{\n    struct dev_i2c *i2c = NULL;\n\n    if (!conf)\n        return -EINVAL;\n    if (conf->base == 0)\n        return -EINVAL;\n\n    if ((conf->idx < 0) || (conf->idx > MAX_I2CS))\n        return -EINVAL;\n\n    i2c = kalloc(sizeof(struct dev_i2c));\n    if (!i2c)\n        return -ENOMEM;\n\n    /* Claim pins for SDA/SCL */\n    gpio_create(&mod_i2c, &conf->pio_sda);\n    gpio_create(&mod_i2c, &conf->pio_scl);\n\n    /* Erase i2c content */\n    memset(i2c, 0, sizeof(struct dev_i2c));\n\n    /* Enable clocks */\n    rcc_periph_clock_enable(conf->rcc);\n    rcc_periph_clock_enable(conf->dma_rcc);\n\n    /* Startup routine */\n    i2c_peripheral_disable(conf->base);\n    i2c_reset(conf->base);\n\n    i2c_set_speed(conf->base, 0);\n\n    //i2c_nack_current(conf->base);\n    i2c_disable_ack(conf->base);\n    i2c_clear_stop(conf->base);\n    i2c_peripheral_enable(conf->base);\n\n    /* Set up device struct */\n    i2c->base = conf->base;\n    i2c->ev_irq = conf->ev_irq;\n    i2c->er_irq = conf->er_irq;\n    i2c->tx_dma_config = &conf->tx_dma;\n    i2c->rx_dma_config = &conf->rx_dma;\n    i2c->state = I2C_STATE_READY;\n    i2c->mutex = mutex_init();\n\n    /* Store address in the DEV_I2C array. */\n    DEV_I2C[conf->idx] = i2c;\n\n    /* Enable interrupts */\n    nvic_set_priority(conf->ev_irq, 1);\n    nvic_enable_irq(conf->ev_irq);\n    nvic_set_priority(conf->er_irq, 1);\n    nvic_enable_irq(conf->er_irq);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/stm32_lowpower.c",
    "content": "#include \"frosted.h\"\n#include \"unicore-mx/cm3/nvic.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include \"unicore-mx/cm3/scb.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/timer.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/exti.h>\n#include <unicore-mx/cm3/systick.h>\n#include <unicore-mx/stm32/pwr.h>\n#include <unicore-mx/stm32/rtc.h>\n\n#define WFE() __asm__ volatile (\"wfe\")\n#if CONFIG_SYS_CLOCK == 48000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_48MHZ\n#elif CONFIG_SYS_CLOCK == 84000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_84MHZ\n#elif CONFIG_SYS_CLOCK == 100000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_100MHZ\n#elif CONFIG_SYS_CLOCK == 120000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_120MHZ\n#elif CONFIG_SYS_CLOCK == 168000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_168MHZ\n#else\n#   error No valid clock speed selected\n#endif\n\n\nint lowpower_init(void)\n{\n    rcc_periph_clock_enable(RCC_PWR);\n    rcc_periph_clock_enable(RCC_RTC);\n\n    /* Disable write protection in the backup range */\n    PWR_CR |= PWR_CR_DBP;\n\n    rtc_unlock();\n    nvic_clear_pending_irq(NVIC_RTC_WKUP_IRQ);\n    nvic_disable_irq(NVIC_RTC_WKUP_IRQ);\n    RTC_ISR &= ~RTC_ISR_WUTF;\n    RTC_CR &= ~(RTC_CR_WUTIE | RTC_CR_WUTE);\n    rtc_lock();\n\n    return 0;\n}\n\n\nint lowpower_sleep(int stdby, uint32_t interval)\n{\n    uint32_t rtc_wup;\n    uint32_t err;\n\n    if (interval < 1)\n        return -1;\n\n    rtc_wup = (interval * 2048) - 1;\n\n    irq_off();\n    rcc_periph_clock_enable(RCC_PWR);\n    rcc_periph_clock_enable(RCC_RTC);\n\n    /* Disable write protection in the backup range */\n    pwr_disable_backup_domain_write_protect();\n\n    /* Enable RTC */\n    RCC_BDCR |= RCC_BDCR_RTCEN;\n\n#ifndef CONFIG_LSE32K\n    /* Enable LSI */\n    rcc_osc_on(RCC_LSI);\n    rcc_wait_for_osc_ready(RCC_LSI);\n\n    /* Select LSI as RTC clock source */\n    RCC_BDCR &= ~RCC_BDCR_RTCSEL_MASK << RCC_BDCR_RTCSEL_SHIFT;\n    RCC_BDCR |= RCC_BDCR_RTCSEL_LSI << RCC_BDCR_RTCSEL_SHIFT;\n#else\n    /* Enable LSE */\n    rcc_osc_bypass_disable(RCC_LSE);\n    rcc_osc_on(RCC_LSE);\n    rcc_wait_for_osc_ready(RCC_LSE);\n\n    /* Select LSE as RTC clock source */\n    RCC_BDCR &= ~RCC_BDCR_RTCSEL_MASK << RCC_BDCR_RTCSEL_SHIFT;\n    RCC_BDCR |= RCC_BDCR_RTCSEL_LSE << RCC_BDCR_RTCSEL_SHIFT;\n#endif\n\n    /* Set up watchdog timer */\n    rtc_unlock();\n    rtc_enable_wakeup_timer();\n\n    rtc_set_wakeup_time((interval - 1), RTC_CR_WUCLKSEL_SPRE);\n\n    rtc_lock();\n    systick_counter_disable();\n    systick_interrupt_disable();\n\n    SCB_SCR |= SCB_SCR_SEVEONPEND;\n    SCB_SCR |= SCB_SCR_SLEEPDEEP;\n\n    if (stdby) {\n        pwr_clear_wakeup_flag();\n        pwr_clear_standby_flag();\n        pwr_set_standby_mode();\n    } else {\n        pwr_clear_wakeup_flag();\n        pwr_voltage_regulator_low_power_in_stop();\n        PWR_CR |= PWR_CR_FPDS;\n    }\n\n    irq_on();\n\n    WFE();\n    WFE();\n\n    SCB_SCR &= ~SCB_SCR_SLEEPDEEP;\n    pwr_clear_wakeup_flag();\n\n#ifdef CLOCK_12MHZ\n    rcc_clock_setup_hse_3v3(&rcc_hse_12mhz_3v3[STM32_CLOCK]);\n#else\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[STM32_CLOCK]);\n#endif\n\n    systick_interrupt_enable();\n    systick_counter_enable();\n    rcc_periph_clock_enable(RCC_PWR);\n    rcc_periph_clock_enable(RCC_RTC);\n    nvic_enable_irq(NVIC_RTC_WKUP_IRQ);\n\n    /* Disable write protection in the backup range */\n    pwr_disable_backup_domain_write_protect();\n\n    /* Disable RTC */\n    RCC_BDCR &= ~RCC_BDCR_RTCEN;\n\n    jiffies += interval * 1000;\n\n    return 0;\n}\n\nvoid rtc_wkup_isr(void)\n{\n    /* Enable RTC */\n    RCC_BDCR |= RCC_BDCR_RTCEN;\n    rtc_unlock();\n    nvic_clear_pending_irq(NVIC_RTC_WKUP_IRQ);\n    nvic_disable_irq(NVIC_RTC_WKUP_IRQ);\n    RTC_ISR &= ~RTC_ISR_WUTF;\n    RTC_CR &= ~(RTC_CR_WUTIE | RTC_CR_WUTE);\n    rtc_lock();\n}\n\n"
  },
  {
    "path": "kernel/drivers/stm32_rng.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: brabo\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#if defined(CONFIG_FRAND)\n#  include \"frand.h\"\n#  include \"fortuna.h\"\n#  include \"crypto/sha256.h\"\n#endif\n#include <stdint.h>\n#include \"rng.h\"\n\n#include <unicore-mx/cm3/common.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/rng.h>\n#define CLOCK_ENABLE(C)                 rcc_periph_clock_enable(C);\n\nstruct dev_rng {\n\tstruct device *dev;\n\tuint32_t base;\n\tuint32_t *random;\n};\n\n#define MAX_RNGS 1\n\n#if defined(CONFIG_FRAND)\nuint32_t req;\n#endif\n\nstatic struct dev_rng DEV_RNG[MAX_RNGS];\n\n#if defined(CONFIG_RNG)\nstatic int devrng_read(struct fnode *fno, void *buf, unsigned int len);\n#endif\n\nstatic struct module mod_devrng = {\n\t.family = FAMILY_FILE,\n#if defined(CONFIG_RNG)\n\t.name = \"urandom\",\n\t.ops.open = device_open,\n\t.ops.read = devrng_read,\n#endif\n};\n\n#if defined(CONFIG_RNG)\nstatic int devrng_read(struct fnode *fno, void *buf, unsigned int len)\n{\n\tstruct dev_rng *rng;\n    int i;\n    uint32_t tmp;\n\n\tif (len == 0)\n\t\treturn len;\n\n\trng = (struct dev_rng *)FNO_MOD_PRIV(fno, &mod_devrng);\n\n\tif (!rng)\n\t\treturn -1;\n\n\tmutex_lock(rng->dev->mutex);\n\n\tuint32_t error_bits = 0;\n\terror_bits = RNG_SR_SEIS | RNG_SR_CEIS | RNG_SR_SECS | RNG_SR_CECS;\n\n    for (i = 0; i < len; i+=4) {\n        uint32_t *rnd_dst = (uint32_t *)((uint8_t *)buf + i);\n\t    if (((RNG_SR & error_bits) != 0) ||\n                ((RNG_SR & RNG_SR_DRDY) != 1)) {\n            rng->random = (uint32_t *)buf;\n            rng_enable_interrupt();\n            rng->dev->task = this_task();\n            mutex_unlock(rng->dev->mutex);\n            task_suspend();\n            return SYS_CALL_AGAIN;\n        }\n    \trng_get_random(rnd_dst);\n    }\n    if (i < len) {\n        rng_get_random(&tmp);\n        memcpy(buf + i, &tmp, len - i);\n    }\n\tmutex_unlock(rng->dev->mutex);\n\treturn len;\n}\n#endif\n\nvoid rng_isr(void)\n{\n\tstruct dev_rng *rng = &DEV_RNG[0];\n\tuint32_t error_bits = 0;\n\terror_bits = RNG_SR_SEIS | RNG_SR_CEIS | RNG_SR_SECS | RNG_SR_CECS;\n\tif ((RNG_SR & RNG_SR_SEIS) != 0) {\n\t\tif ((RNG_SR & RNG_SR_DRDY) == 1) {\n\t\t\tuint32_t dummy;\n\t\t\trng_get_random(&dummy);\n\t\t}\n\t\trng_disable();\n\t\trng_enable();\n\t\tRNG_SR &= ~RNG_SR_SEIS;\n\t}\n\tif ((RNG_SR & RNG_SR_CEIS) != 0) {\n\t\trcc_periph_reset_pulse(RST_RNG);\n\t\trng_disable();\n\t\trng_enable();\n\t\tRNG_SR &= ~RNG_SR_CEIS;\n\t}\n\tif (((RNG_SR & error_bits) == 0) && ((RNG_SR & RNG_SR_DRDY) == 1)) {\n\t\tuint32_t random;\n\t\trng_get_random(&random);\n#if defined(CONFIG_FRAND)\n\t\tfortuna_accu(0, 0, (uint8_t *)&random, 4);\n\t\tif (req == 0) {\n\t\t\trng_disable_interrupt();\n\t\t} else {\n\t\t\treq--;\n\t\t}\n#else\n\t\tmemcpy(rng->random, &random, 4);\n\t\trng_disable_interrupt();\n\t\ttask_resume(rng->dev->task);\n#endif\n\t}\n}\n\n#if defined(CONFIG_RNG)\nint rng_create(uint32_t base, uint32_t rcc)\n{\n    static uint32_t id = 0;\n\tstruct dev_rng *r = &DEV_RNG[id];\n    struct fnode *devfs;\n    CLOCK_ENABLE(rcc);\n\n    devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return -ENOENT;\n\tr->dev = device_fno_init(&mod_devrng, mod_devrng.name, devfs, FL_RDONLY, r);\n\tr->base = base;\n    rng_enable();\n    return id++;\n}\n#endif\n\n#if defined(CONFIG_FRAND)\nstatic const struct frand_ops rng_frandops = {  };\n\nstatic struct frand_info rng_info = { .frandops = (struct frand_ops *)&rng_frandops };\n#endif\n\nint rng_init(void)\n{\n\tregister_module(&mod_devrng);\n#if defined(CONFIG_FRAND)\n\tregister_frand(&rng_info);\n\treq = FORTUNA_ENCRYPT_KEY_SIZE * ((SHA256_DIGEST_SIZE / sizeof(word32)) * (SHA256_BLOCK_SIZE / sizeof(word32)));\n\trng_enable_interrupt();\n#endif\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/stm32_sdio.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Original Author: Chuck M. (see https://github.com/ChuckM/stm32f4-sdio-driver/)\n *      Re-adapted for frosted by: Daniele Lacamera\n *\n *      Permission to release under the terms of GPLv2 are granted by the\n *      copyright holders.\n *\n */\n\n\n\n\n/*\n * SDIO Bus Driver layer. This code sends commands and drives\n * the SDIO peripheral on the STM32F4xx, there is a layer above\n * this, the SD Card driver, which uses this driver to talk to\n * SD Cards. The SPI driver can also talk to SD Cards, hence the\n * split at this layer.\n *\n * Note that the simple implementation for the SDIO driver runs\n * in a 'polled' mode. This is easier to explain and debug and\n * sufficient for the first few projects. A more sophisticated\n * version with DMA and interrupts will follow.\n *\n\n *\n *\n */\n\n#include <stdint.h>\n#include <unicore-mx/stm32/sdio.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/cm3/nvic.h>\n#include \"stm32_sdio.h\"\n#include \"frosted.h\"\n#include \"device.h\"\n#include \"sdio.h\"\n\n#define     MAX_SDIOS   1\n\n/* Frosted device driver hook */\nstatic struct module mod_sdio;\n\nstatic struct dev_sd *DEV_SD[MAX_SDIOS] = { };\n\n/*\n * Some Global defines, collected here.\n */\n\n/*\n * Not defined by default\n */\n#ifndef NULL\n#define NULL (void *)(0x00000000)\n#endif\n\n/*\n * Helper defines to pull out various bit fields of the CSD for\n * the size calculation.\n */\n#define SDIO_CSD_VERSION(x) stm32_sdio_bit_slice(x->csd, 128, 127, 126)\n#define SDIO_CSD1_CSIZE_MULT(x) stm32_sdio_bit_slice(x->csd, 128, 49, 47)\n#define SDIO_CSD1_RBLKLEN(x) stm32_sdio_bit_slice(x->csd, 128, 83, 80)\n#define SDIO_CSD1_CSIZE(x) stm32_sdio_bit_slice(x->csd, 128, 73, 62)\n#define SDIO_CSD2_CSIZE(x) stm32_sdio_bit_slice(x->csd, 128, 69, 48)\n\n/*\n * Conveniently swaps the bytes in a long around\n * used by the SCR code.\n */\n#define byte_swap(val) \\\n        asm(\"rev %[swap], %[swap]\" : [swap] \"=r\" (val) : \"0\" (val));\n\n/*\n * sdio_bus\n *\n * Set the bus width and the clock speed for the\n * SDIO bus.\n *\n * Returns 0 on success\n *      -1 illegal bit specification\n *      -2 illegal clock specification\n */\nint\nstm32_sdio_bus(struct dev_sd *sd, int bits, enum SDIO_CLOCK_DIV freq) {\n    int clkreg = 0;\n\n    switch (bits) {\n        case 1:\n            clkreg |= SDIO_CLKCR_WIDBUS_1;\n            break;\n        case 4:\n            clkreg |= SDIO_CLKCR_WIDBUS_4;\n            break;\n        default:\n            return -1;\n    }\n    switch (freq) {\n        case SDIO_24MHZ:\n            break;\n        case SDIO_16MHZ:\n            clkreg |= 1;\n            break;\n        case SDIO_12MHZ:\n            clkreg |= 2;\n            break;\n        case SDIO_8MHZ:\n            clkreg |= 8;\n            break;\n        case SDIO_4MHZ:\n            clkreg |= 10;\n            break;\n        case SDIO_1MHZ:\n            clkreg |= 46;\n            break;\n        case SDIO_400KHZ:\n            clkreg |= 118;\n            break;\n        default:\n            return -2;\n    }\n    clkreg |= SDIO_CLKCR_CLKEN;\n    SDIO_CLKCR(sd->base) = clkreg;\n    return 0;\n}\n\n/*\n * Reset the state of the SDIO bus and peripheral. This code tries\n * to reset the bus *AND* the card if one is plugged in. The bus\n * can be reset by software but the card is reset by powering it down.\n *\n * The SDIO_POWER_STATE tells the code which state to leave the bus in,\n * powered up or powered down.\n *\n * If the state is POWER_ON, then the bus is reset to 400Khz, 1 bit wide\n * which is what he spec requires. Once the type and capabilities of the\n * card have been determined, it can be upgraded.\n */\nvoid\nstm32_sdio_reset(struct dev_sd *sd, enum SDIO_POWER_STATE state) {\n\n    /* Step 1 power off the interface */\n    SDIO_POWER(sd->base) = SDIO_POWER_PWRCTRL_PWROFF;\n\n    /* reset the SDIO peripheral interface */\n    rcc_peripheral_reset(sd->rcc_rst_reg, sd->rcc_rst);\n    rcc_peripheral_clear_reset(sd->rcc_rst_reg, sd->rcc_rst);\n\n    if (state == SDIO_POWER_ON) {\n        SDIO_POWER(sd->base) = SDIO_POWER_PWRCTRL_PWRON;\n        stm32_sdio_bus(sd, 1, SDIO_400KHZ); // required by the spec\n    }\n}\n\n/*\n * The error message catalog.\n */\nstatic const char *__sdio_error_msgs[] = {\n    \"Success\",\n    \"Command Timeout\",              // -1\n    \"Command CRC Failure\",          // -2\n    \"Soft Timeout (No Response)\",   // -3\n    \"Data CRC Failure\",             // -4\n    \"RX FIFO Overrun\",              // -5\n    \"TX FIFO Underrun\",             // -6\n    \"Unsupported Card\"              // -7\n};\n\n#define SDIO_ESUCCESS    0\n#define SDIO_ECTIMEOUT  -1\n#define SDIO_ECCRCFAIL  -2\n#define SDIO_ENORESP    -3\n#define SDIO_EDCRCFAIL  -4\n#define SDIO_ERXOVERR   -5\n#define SDIO_ETXUNDER   -6\n#define SDIO_EBADCARD   -7\n#define SDIO_EUNKNOWN   -8\n\n/*\n * Return a text string description of the error code.\n */\nconst char *\nstm32_sdio_errmsg(int err) {\n    return (err <= SDIO_EUNKNOWN) ? (const char *) \"Unknown Error\" :\n                                __sdio_error_msgs[0-err];\n}\n\n/*\n * stm32_sdio_bit_slice - helper function\n *\n * A number of the things the SDIO returns are in bit\n * fields. This code is designed to slice out a range\n * of bits and return them as a value (up to 32 bits\n * worth).\n */\nuint32_t\nstm32_sdio_bit_slice(uint32_t a[], int bits, int msb, int lsb) {\n    uint32_t t;\n    int i;\n\n    if (((msb >= bits) || (msb < 0)) ||\n        (lsb > msb) ||\n        ((lsb < 0) || (lsb >= bits))) {\n        kprintf(\"Bad Slice values.\\r\\n\");\n        return 0;\n    }\n    t = 0;\n    for (i = msb; i > lsb; i--) {\n        t |= (a[((bits-1) - i)/32] >> (i % 32)) & 0x1;\n        t <<= 1;\n    }\n    t |= (a[((bits-1) - lsb)/32] >> (lsb % 32)) & 0x1;\n    return t;\n}\n\n/*\n * A convienence define. These are the flags we care about when\n * sending a command. During command processing SDIO_STA_CMDACT\n * will be set.\n */\n#define COMMAND_FLAGS   (SDIO_STA_CMDSENT |\\\n                         SDIO_STA_CCRCFAIL |\\\n                         SDIO_STA_CMDREND |\\\n                         SDIO_STA_CTIMEOUT)\n\n/*\n * Send a command over the SDIO bus.\n * Passed a command (8 bit value) and an argument (32 bit value)\n * This command figures out if the command will return a short (32 bit)\n * or long (64 bit) response. It is up to the calling program to pull\n * data from the long response commands.\n * Passed:\n *          cmd - Command to execute\n *          arg - Argument to pass to the command\n *          buf - pointer to a long aligned buffer if data\n *          len - expected length of buffer (in bytes)\n */\nint\nstm32_sdio_command(struct dev_sd *sd, uint32_t cmd, uint32_t arg)\n{\n    uint32_t    tmp_val;\n    int         error = 0;\n\n    tmp_val = SDIO_CMD(sd->base) & ~0x7ff;            // Read pre-existing state\n    tmp_val |= (cmd & SDIO_CMD_CMDINDEX_MSK);   // Put the Command in\n    tmp_val |= SDIO_CMD_CPSMEN;                 // We'll be running CPSM\n\n    switch(cmd) {\n        case 0:\n            tmp_val |= SDIO_CMD_WAITRESP_NO_0;\n            break;\n        case 2:\n        case 9:\n            tmp_val |= SDIO_CMD_WAITRESP_LONG;\n            break;\n        default:\n            tmp_val |= SDIO_CMD_WAITRESP_SHORT; // the common case\n            break;\n    }\n    /* If a data transaction is in progress, wait for it to finish */\n\n    while ((cmd != 12) &  (SDIO_STA(sd->base) & (SDIO_STA_RXACT | SDIO_STA_TXACT)));;\n\n\n    /*\n     * EXECUTE:\n     *    o Reset all status bits\n     *    o Put ARG into SDIO ARG\n     *    o reset the error indicator\n     *    o Enable all interrupts.\n     *    o Do the command\n     */\n    SDIO_ICR(sd->base) = 0x7ff;           // Reset everything that isn't bolted down.\n    SDIO_ARG(sd->base) = arg;\n    SDIO_CMD(sd->base) = tmp_val;\n    /*\n     * In a polled mode we should be able to just read the status bits\n     * directly.\n     */\n    tmp_val = 0;\n    do {\n        tmp_val |= (SDIO_STA(sd->base) & 0x7ff);\n    } while ((SDIO_STA(sd->base) & SDIO_STA_CMDACT) || (! tmp_val));;\n    SDIO_ICR(sd->base) = tmp_val;\n\n    /*\n     * Compute the error here. Which can be one of\n     * -- Success (either CMDSENT or CMDREND depending on response)\n     * -- Timeout (based on CTIMEOUT)\n     * -- No Response (based on no response in the time alloted)\n     * -- CRC Error (based on CCRCFAIL)\n     */\n    if (! tmp_val) {\n        error = SDIO_ENORESP;\n    } else if (tmp_val & SDIO_STA_CCRCFAIL) {\n        error = SDIO_ECCRCFAIL;\n    } else if (tmp_val & (SDIO_STA_CMDREND | SDIO_STA_CMDSENT)) {\n        error = SDIO_ESUCCESS;\n    } else if (tmp_val & SDIO_STA_CTIMEOUT) {\n        error = SDIO_ECTIMEOUT;\n    } else {\n        error = SDIO_EUNKNOWN;\n    }\n\n    return error;\n}\n\n\n/* our static data buffer we use for data movement commands */\nstatic uint32_t data_buf[129];\nstatic int data_len;\n\n/*\n * Helper function - sdio_select\n *\n * This function \"selects\" a card using CMD7, note that if\n * you select card 0 that deselects the card (RCA is not allowed\n * to be 0)\n */\nstatic int\nsdio_select(struct dev_sd *sd, int rca) {\n    int err;\n\n    err = stm32_sdio_command(sd, 7, rca << 16);\n    if ((rca == 0) && (err == SDIO_ECTIMEOUT)) {\n        return 0;   // \"cheat\" a timeout selecting 0 is a successful deselect\n    }\n    return err;\n}\n\n/*\n * Helper function - sdio_scr\n *\n * Unlike the CID and CSD functions this function transfers data\n * so it needs to use the DPSM.\n *\n * Note that data over the wire is byte swapped so we swap it back\n * to \"fix\" it.\n *\n * Note when this return 0 the first two longs in the data_buf are\n * the SCR register.\n */\n\nstatic int\nsdio_scr(struct dev_sd *sd, SDIO_CARD c) {\n    int err;\n    uint32_t    tmp_reg;\n    int ndx;\n\n    /* Select the card */\n    err = sdio_select(sd, c->rca);\n    if (! err) {\n        /* Set the Block Size */\n        err = stm32_sdio_command(sd, 16, 8);\n        if (! err) {\n            /* APPCMD (our RCA) */\n            err = stm32_sdio_command(sd, 55, c->rca << 16);\n            if (! err) {\n                SDIO_ICR(sd->base) = 0xFFFFFFFF; /* Clear all status flags */\n                SDIO_DTIMER(sd->base) = 0xffffffff;\n                SDIO_DLEN(sd->base) = 8;\n                SDIO_DCTRL(sd->base) = SDIO_DCTRL_DBLOCKSIZE_3 |\n                             SDIO_DCTRL_DTDIR |\n                             SDIO_DCTRL_DTEN;\n                /* ACMD51 - Send SCR */\n                err = stm32_sdio_command(sd, 51, 0);\n                if (! err) {\n                    data_len = 0;\n                    do {\n                        tmp_reg = SDIO_STA(sd->base);\n                        if (tmp_reg & SDIO_STA_RXDAVL) {\n                            data_buf[data_len++] = SDIO_FIFO(sd->base);\n                        }\n                    } while (tmp_reg & SDIO_STA_RXACT);\n                    if ((tmp_reg & SDIO_STA_DBCKEND) == 0) {\n                        if (tmp_reg & SDIO_STA_DCRCFAIL) {\n                            err = SDIO_EDCRCFAIL;\n                        } else if (tmp_reg & SDIO_STA_RXOVERR) {\n                            err = SDIO_ERXOVERR;\n                        } else {\n                            err = SDIO_EUNKNOWN; // XXX: unknown error\n                        }\n                    }\n                    if (! err) {\n                        for (ndx = 0; ndx < 2; ndx++) {\n                            byte_swap(data_buf[ndx]);\n                            c->scr[ndx] = data_buf[ndx];\n                        }\n                    }\n                }\n            }\n        }\n    }\n    (void) sdio_select(sd, 0);\n    if (err)\n        kprintf(\"[SDIO] %s\\n\", stm32_sdio_errmsg(err));\n    return err;\n}\n\n/*\n * Read a Block from our Card\n *\n * NB: There is a possibly useless test in this code, during the read\n * phase it allows that the SDIO card might try to send more than 512\n * bytes (128 32 bit longs) and allows it to do so, constantly over\n * writing the last long in the just-in-case-over-long-by-1 data buffer.\n * To compromise the system you would need a borked or custom crafted\n * sdio card which did that.\n */\n\nint sdio_block_read(struct fnode *fno, void *_buf, uint32_t lba, int offset, int count)\n{\n    int err;\n    uint32_t tmp_reg;\n    uint32_t addr = lba;\n    uint8_t *t;\n    int ndx, bdx = 0;\n    struct dev_sd *sd;\n    SDIO_CARD c;\n    uint8_t *buf = _buf;\n\n\n    sd = (struct dev_sd *)FNO_MOD_PRIV(fno, &mod_sdio);\n    if (!sd)\n        return -1;\n    c = sd->card;\n\n    if (! SDIO_CARD_CCS(c)) {\n        addr = lba * 512; // non HC cards use byte address\n    }\n    err = sdio_select(sd, c->rca);\n    if (! err) {\n        err = stm32_sdio_command(sd, 16, 512);\n        if (!err) {\n            SDIO_DTIMER(sd->base) = 0xffffffff;\n            SDIO_DLEN(sd->base) = 512;\n            SDIO_DCTRL(sd->base) = SDIO_DCTRL_DBLOCKSIZE_9 |\n                         SDIO_DCTRL_DTDIR |\n                         SDIO_DCTRL_DTEN;\n            err = stm32_sdio_command(sd, 17, addr);\n            if (! err) {\n                data_len = 0;\n                do {\n                    tmp_reg = SDIO_STA(sd->base);\n                    if (tmp_reg & SDIO_STA_RXDAVL) {\n                        data_buf[data_len] = SDIO_FIFO(sd->base);\n                        if (data_len < 128) {\n                            ++data_len;\n                        }\n                    }\n                } while (tmp_reg & SDIO_STA_RXACT);\n                if ((tmp_reg & SDIO_STA_DBCKEND) == 0) {\n                    if (tmp_reg & SDIO_STA_DCRCFAIL) {\n                        err = SDIO_EDCRCFAIL;\n                    } else if (tmp_reg & SDIO_STA_RXOVERR) {\n                        err = SDIO_ERXOVERR;\n                    } else {\n                        err = SDIO_EUNKNOWN; // Unknown Error!\n                    }\n                } else {\n                    t = (uint8_t *)(data_buf);\n                    /* copy out to the user buffer */\n                    for (ndx = offset; ndx < (offset + count); ndx ++) {\n                        buf[bdx++] = t[ndx];\n                    }\n                }\n            }\n        }\n    }\n    // deselect the card\n    (void) sdio_select(sd, 0);\n    if (err)\n        kprintf(\"[SDIO] %s\\n\", stm32_sdio_errmsg(err));\n    return err;\n}\n\n/*\n * Write a Block from our Card\n */\n//int\n//sdio_block_write(SDIO_CARD c, uint32_t lba, uint8_t *buf) {\nint\nsdio_block_write(struct fnode *fno, void *_buf, uint32_t lba, int offset, int count)\n{\n    int err;\n    uint32_t tmp_reg;\n    uint32_t addr = lba;\n    uint8_t *t;\n    int ndx;\n    struct dev_sd *sd;\n    SDIO_CARD c;\n    uint8_t *buf = _buf;\n\n\n    sd = (struct dev_sd *)FNO_MOD_PRIV(fno, &mod_sdio);\n    if (!sd)\n        return -1;\n    c = sd->card;\n\n    if (! SDIO_CARD_CCS(c)) {\n        addr = lba * 512; // non HC cards use byte address\n    }\n\n    /*\n     * Copy buffer to our word aligned buffer. Nominally you\n     * can just use the passed in buffer and cast it to a\n     * uint32_t * but that can cause issues if it isn't\n     * aligned.\n     */\n    t = (uint8_t *)(data_buf);\n    for (ndx = 0; ndx < 512; ndx ++) {\n        *t = *buf;\n        buf++;\n        t++;\n    }\n    err = sdio_select(sd, c->rca);\n    if (! err) {\n        /* Set Block Size to 512 */\n        err = stm32_sdio_command(sd, 16, 512);\n        if (!err) {\n            SDIO_DTIMER(sd->base) = 0xffffffff;\n            SDIO_DLEN(sd->base) = 512;\n            SDIO_DCTRL(sd->base) = SDIO_DCTRL_DBLOCKSIZE_9 |\n                         SDIO_DCTRL_DTEN;\n            err = stm32_sdio_command(sd, 24, addr + offset);\n            if (! err) {\n                data_len = 0;\n                do {\n                    tmp_reg = SDIO_STA(sd->base);\n                    if (tmp_reg & SDIO_STA_TXFIFOHE) {\n                        SDIO_FIFO(sd->base) = data_buf[data_len];\n                        if (data_len < 128) {\n                            ++data_len;\n                        }\n                    }\n                } while (tmp_reg & SDIO_STA_TXACT);\n                if ((tmp_reg & SDIO_STA_DBCKEND) == 0) {\n                    if (tmp_reg & SDIO_STA_DCRCFAIL) {\n                        err = SDIO_EDCRCFAIL;\n                    } else if (tmp_reg & SDIO_STA_TXUNDERR) {\n                        err = SDIO_ETXUNDER;\n                    } else {\n                        err = SDIO_EUNKNOWN; // Unknown Error!\n                    }\n                }\n            }\n        }\n    }\n    // deselect the card\n    (void) sdio_select(sd, 0);\n    if (err)\n        kprintf(\"[SDIO] %s\\n\", stm32_sdio_errmsg(err));\n    return err;\n}\n\n/*\n * sdio-status - Get Card Status page\n *\n * This function fetches the SD Card Status page and\n * copies it into the CARD structure.\n */\n/*\nint\nsdio_status(SDIO_CARD c) {\n    uint32_t tmp_reg;\n    int ndx;\n    int err;\n\n    err = sdio_select(c->rca);\n    if (! err) {\n        err = stm32_sdio_command(16, 64);\n        if (! err) {\n            err = stm32_sdio_command(55, c->rca << 16);\n            if (! err) {\n                SDIO_DTIMER = 0xffffffff;\n                SDIO_DLEN = 64;\n                SDIO_DCTRL = SDIO_DCTRL_DBLOCKSIZE_6 |\n                             SDIO_DCTRL_DTDIR |\n                             SDIO_DCTRL_DTEN; */\n                /* ACMD13 - Send Status Reg */ /*\n                err = stm32_sdio_command(13, 0);\n                if (! err) {\n                    data_len = 0;\n                    do {\n                        tmp_reg = SDIO_STA;\n                        if (tmp_reg & SDIO_STA_RXDAVL) {\n                            data_buf[data_len] = SDIO_FIFO;\n                            if (data_len < 128) {\n                                ++data_len;\n                            }\n                        }\n                    } while (tmp_reg & SDIO_STA_RXACT);\n                    if ((tmp_reg & SDIO_STA_DBCKEND) == 0) {\n                        if (tmp_reg & SDIO_STA_DCRCFAIL) {\n                            err = SDIO_EDCRCFAIL;\n                        } else if (tmp_reg & SDIO_STA_RXOVERR) {\n                            err = SDIO_ERXOVERR;\n                        } else {\n                            err = SDIO_EUNKNOWN; // Unknown Error!\n                        }\n                    } else {\n                        for (ndx = 0; ndx < 16; ndx++) {\n                            byte_swap(data_buf[ndx]);\n                            c->status[ndx] = data_buf[ndx];\n                        }\n                    }\n                    (void) sdio_select(0);\n                }\n            }\n        }\n    }\n\n    if (err)\n        kprintf(\"[SDIO] %s\\n\", stm32_sdio_errmsg(err));\n    return err;\n}\n*/\n\nstatic struct SDIO_CARD_DATA __sdio_card_data;\n#define MAX_RETRIES 5\n\n/*\n * stm32_sdio_open - Prepare to use SDIO card\n *\n * This function resets the SDIO bus and identifies the\n * card (if any) that is plugged in. If there is no card\n * present, or an error in figuring out what the card is\n * (for example its an old MMC card) the function returns\n * NULL. If it fails and you have logging enabled you can\n * look at the last few commands sent.\n */\nSDIO_CARD\nstm32_sdio_open(struct dev_sd *sd) {\n    int err;\n    int i;\n    uint8_t *t;\n    uint32_t tmp_reg;\n    SDIO_CARD res = &__sdio_card_data;\n\n    // basically bset(0, __sdio_card_data)\n    t = (uint8_t *) &__sdio_card_data;\n    for (i = 0; i < (int) sizeof(__sdio_card_data); i++) {\n        *t++ = 0;\n    }\n    stm32_sdio_reset(sd, SDIO_POWER_ON);\n    err = stm32_sdio_command(sd, 0, 0);\n    if (!err) {\n        err = stm32_sdio_command(sd, 8, 0x1aa);\n        if (!err) {\n            // Woot! We support CMD8 so we're a v2 card at least */\n            tmp_reg = SDIO_RESP1(sd->base);\n            __sdio_card_data.props = 1;\n            i = 0;\n            err = stm32_sdio_command(sd, 5, 0);\n            if (! err) {\n                // It is an SDIO card which is unsupported!\n                err = SDIO_EBADCARD;\n                return NULL;\n            }\n            do {\n                err = stm32_sdio_command(sd, 55, 0); // broadcast ACMD\n                if (err) {\n                    break;   // try again\n                }\n                // Testing Card Busy, Voltage match, and capacity\n                err = stm32_sdio_command(sd, 41, 0xc0100000);\n                if (err != -2) {            // Expect CCRCFAIL here\n                    break;               // try again\n                }\n                tmp_reg = SDIO_RESP1(sd->base); // what did the card send?\n                if ((tmp_reg & 0x80000000) == 0) {\n                    continue;               // still powering up\n                }\n                res->ocr = tmp_reg;           // Ok OCR is valid\n                break;\n            } while (++i < MAX_RETRIES);\n            if (res->ocr) {\n                err = stm32_sdio_command(sd, 2, 0);\n                if (! err) {\n                    res->cid[0] = SDIO_RESP1(sd->base);\n                    res->cid[1] = SDIO_RESP2(sd->base);\n                    res->cid[2] = SDIO_RESP3(sd->base);\n                    res->cid[3] = SDIO_RESP4(sd->base);\n                    err = stm32_sdio_command(sd, 3, 0);   // get the RCA\n                    if (! err) {\n                        tmp_reg = SDIO_RESP1(sd->base);\n                        res->rca = (tmp_reg >> 16) & 0xffff;\n                        if (! res->rca) {\n                            /*\n                             * If the card says '0' tell it to pick\n                             * we assume this will work because the\n                             * previous send RCA worked and the card\n                             * should be in the ident state if it is\n                             * functioning correctly.\n                             */\n                            (void) stm32_sdio_command(sd, 3, 0); // try again\n                            tmp_reg = SDIO_RESP1(sd->base);\n                            res->rca = (tmp_reg >> 16) & 0xffff;\n                        }\n                        err = stm32_sdio_command(sd, 9, res->rca << 16);\n                        if (! err) {\n                            res->csd[0] = SDIO_RESP1(sd->base);\n                            res->csd[1] = SDIO_RESP2(sd->base);\n                            res->csd[2] = SDIO_RESP3(sd->base);\n                            res->csd[3] = SDIO_RESP4(sd->base);\n                            err = sdio_scr(sd, res); // Capture the SCR\n                            if (! err) {\n                                /* All SD Cards support 4 bit bus and 24Mhz */\n                                err = sdio_select(sd, res->rca);\n                                if (! err) {\n                                    err = stm32_sdio_command(sd, 55, res->rca << 16);\n                                    if (! err) {\n                                        err = stm32_sdio_command(sd, 6, 2);\n                                        if (! err) {\n                                            //XXX stm32_sdio_bus(4, SDIO_24MHZ);\n                                            //Seems we have speed issues for now...\n                                            stm32_sdio_bus(sd, 4, SDIO_12MHZ);\n                                            (void) sdio_select(sd, 0);\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    /* Compute the size of the card based on fields in the CSD\n     * block. There are two kinds, V1 or V2.\n     * In the V1 Case :\n     *     Size = 1<<BLOCK_LEN * 1<<(MULT+2) * (C_SIZE+1) bytes.\n     * In the V2 Case :\n     *     Size = (C_SIZE + 1) * 512K bytes.\n     * But for our structure we want the size in 512 byte \"blocks\"\n     * since that is the addressing unit we're going to export so\n     * we compute the size / 512 as the \"size\" for the structure.\n     */\n\n    if (! err) {\n        res->size = 0;\n        switch (SDIO_CSD_VERSION(res)) {\n            case 0:\n                tmp_reg = ((1 << (SDIO_CSD1_CSIZE_MULT(res) + 2)) *\n                           ( 1 << SDIO_CSD1_RBLKLEN(res))) >> 9;\n                res->size = tmp_reg * (SDIO_CSD1_CSIZE(res) + 1);\n                break;\n            case 1:\n                res->size = (SDIO_CSD2_CSIZE(res)+1) << 10;\n                break;\n            default:\n                res->size = 0; // Bug if its not CSD V1 or V2\n        }\n    }\n\n    if (err)\n        kprintf(\"[SDIO] %s\\n\", stm32_sdio_errmsg(err));\n    return (err == 0) ? res : NULL;\n}\n\nstatic void stm32_sdio_card_detect(void *arg)\n{\n    struct dev_sd *sd = DEV_SD[0];\n\n    struct fnode *dev = arg;\n\n    sd->card = stm32_sdio_open(DEV_SD[0]);\n    if (!sd->card) {\n        return;\n    }\n    kprintf(\"Found SD card in microSD slot.\\r\\n\");\n\n}\n\n/*\n * Set up the GPIO pins and peripheral clocks for the SDIO\n * system. The code should probably take an option card detect\n * pin, at the moment it uses the one used by the Embest board.\n */\nstatic void sdio_hw_init(struct sdio_config *conf)\n{\n    /* Enable clocks for SDIO and DMA2 */\n    gpio_create(&mod_sdio, &conf->pio_dat0);\n    gpio_create(&mod_sdio, &conf->pio_dat1);\n    gpio_create(&mod_sdio, &conf->pio_dat2);\n    gpio_create(&mod_sdio, &conf->pio_dat3);\n    gpio_create(&mod_sdio, &conf->pio_clk);\n    gpio_create(&mod_sdio, &conf->pio_cmd);\n    if (conf->card_detect_supported)\n        gpio_create(&mod_sdio, &conf->pio_cd);\n    rcc_peripheral_enable_clock(conf->rcc_reg, conf->rcc_en);\n}\n\n\nint sdio_init(struct sdio_config *conf)\n{\n    SDIO_CARD card;\n    struct fnode *devfs;\n\n    /* Initialize sdio RCC and pins */\n    sdio_hw_init(conf);\n\n    devfs = fno_search(\"/dev\");\n\n    if (!devfs)\n        return -ENOENT;\n\n    struct dev_sd *sd;\n    sd = kalloc(sizeof(struct dev_sd));\n    if (!sd)\n        return -ENOMEM;\n\n    char name[4] = \"sd0\";\n    memset(sd, 0, sizeof (struct dev_sd));\n    sd->base = conf->base;\n    sd->rcc_rst_reg = conf->rcc_rst_reg;\n    sd->rcc_rst = conf->rcc_rst;\n    sd->dev = device_fno_init(&mod_sdio, name, devfs, FL_BLK, sd);\n    DEV_SD[conf->devidx] = sd;\n\n    memset(&mod_sdio, 0, sizeof(mod_sdio));\n    kprintf(\"Successfully initialized SDIO module.\\r\\n\");\n    strcpy(mod_sdio.name,\"sdio\");\n\n\n    //mod_sdio.ops.close = sdio_close;\n    mod_sdio.ops.block_read = sdio_block_read;\n    mod_sdio.ops.block_write = sdio_block_write;\n\n    register_module(&mod_sdio);\n    tasklet_add(stm32_sdio_card_detect, devfs);\n    return 0;\n}\n\n\n"
  },
  {
    "path": "kernel/drivers/stm32_sdio.h",
    "content": "#include \"frosted.h\"\n/* this define lets the init code know that you are using a GPIO as a card\n * detect pin */\n#define SDIO_HAS_CARD_DETECT\n\nenum SDIO_CLOCK_DIV {\n    SDIO_24MHZ = 0,\n    SDIO_16MHZ,\n    SDIO_12MHZ,\n    SDIO_8MHZ,\n    SDIO_4MHZ,\n    SDIO_1MHZ,\n    SDIO_400KHZ\n};\n\nenum SDIO_POWER_STATE {\n    SDIO_POWER_ON,\n    SDIO_POWER_OFF\n};\n\n#define SDIO_CARD_CCS(c)     (((c)->ocr & 0x40000000) != 0)\n#define SDIO_CARD_UHS2(c)   (((c)->ocr & 0x40000000) != 0)\n#define SDIO_CARD_LVOK(c)   (((c)->ocr & 0x01000000) != 0)\n\ntypedef struct SDIO_CARD_DATA {\n    uint32_t    props;\n    uint32_t    ocr;\n    uint32_t    cid[4];\n    uint32_t    csd[4];\n    uint32_t    scr[2];\n    uint32_t    status[16];\n    uint32_t    size;\n    uint16_t    rca;\n} * SDIO_CARD;\n\nstruct dev_sd {\n    struct device *dev;\n    uint32_t base;\n    uint32_t *rcc_rst_reg;\n    uint32_t rcc_rst;\n    SDIO_CARD card;\n};\n\nint stm32_sdio_bus(struct dev_sd *sd, int bits, enum SDIO_CLOCK_DIV freq);\nint stm32_sdio_init(void);\nvoid stm32_sdio_reset(struct dev_sd *sd, enum SDIO_POWER_STATE state);\nSDIO_CARD stm32_sdio_open(struct dev_sd *sd);\nint stm32_sdio_command(struct dev_sd *sd, uint32_t cmd, uint32_t arg);\nint stm32_sdio_readblock(SDIO_CARD, uint32_t lba, uint8_t *buf);\nint stm32_sdio_writeblock(SDIO_CARD, uint32_t lba, uint8_t *buf);\n//int stm32_sdio_status(SDIO_CARD);\nvoid stm32_sdio_print_log(int console, int number_of_entries);\nconst char *stm32_sdio_errmsg(int err);\nuint32_t stm32_sdio_bit_slice(uint32_t a[], int bits, int msb, int lsb);\n\n/* API for sd_bus clock setting */\nenum SD_CLOCK_DIV {\n    CLOCK_24MHZ = 0,\n    CLOCK_16MHZ,\n    CLOCK_12MHZ,\n    CLOCK_8MHZ,\n    CLOCK_4MHZ,\n    CLOCK_1MHZ,\n    CLOCK_400KHZ\n};\n\n//int stm32_sd_bus(int bits, enum SD_CLOCK_DIV freq);\n"
  },
  {
    "path": "kernel/drivers/stm32_spi.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include <unicore-mx/cm3/nvic.h>\n\n#include <unicore-mx/stm32/dma.h>\n#include \"unicore-mx/stm32/spi.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/gpio.h>\n#include \"device.h\"\n#include <stdint.h>\n#include \"cirbuf.h\"\n#include \"dma.h\"\n#include \"spi.h\"\n#include \"locks.h\"\n\n\n/* Dummy module, for gpio claiming only. */\nstatic struct module mod_spi = {\n    .family = FAMILY_DEV,\n    .name = \"spi\"\n};\n\nstruct dev_spi {\n    struct device * dev;\n    uint32_t base;\n    uint32_t irq;\n    void (*isr)(struct spi_slave *sl);\n    struct spi_slave *sl;\n    const struct dma_config * tx_dma_config;\n    const struct dma_config * rx_dma_config;\n    mutex_t *mutex;\n};\n\n#define MAX_SPIS 4\n\nstatic struct dev_spi *DEV_SPI[MAX_SPIS] = { };\n\nstatic void spi_rx_dma_complete(struct spi_slave * sl)\n{\n    struct dev_spi *spi;\n    if (!sl)\n        return;\n    spi = DEV_SPI[sl->bus];\n    if (!spi)\n        return;\n    if (spi->isr)\n        spi->isr(sl);\n}\n\n#ifdef CONFIG_SPI_1\nvoid spi_isr(void)\n{\n}\n\nvoid dma2_stream2_isr()\n{\n    dma_clear_interrupt_flags(DMA1, DMA_STREAM0, DMA_LISR_TCIF0);\n    spi_rx_dma_complete(DEV_SPI[1]->sl);\n    spi_disable(DEV_SPI[1]->base);\n    mutex_unlock(DEV_SPI[1]->mutex);\n}\n\nvoid dma2_stream3_isr()\n{\n    dma_clear_interrupt_flags(DMA1, DMA_STREAM6, DMA_LISR_TCIF0);\n}\n#endif\n\nint devspi_xfer(struct spi_slave *sl, const char *obuf, char *ibuf, unsigned int len)\n{\n    struct dev_spi *spi;\n    int i;\n    if (len <= 0)\n        return len;\n\n    spi = DEV_SPI[sl->bus];\n    if (!spi)\n        return -EINVAL;\n\n    mutex_lock(spi->mutex);\n    spi_reset(spi->base);\n    spi->sl = sl;\n    //init_dma(spi->tx_dma_config, (uint32_t)obuf, len);\n    //init_dma(spi->rx_dma_config, (uint32_t)ibuf, len);\n\n    //dma_enable_transfer_complete_interrupt(spi->rx_dma_config->base, spi->rx_dma_config->stream);\n    //nvic_set_priority(spi->rx_dma_config->irq, 1);\n    //nvic_enable_irq(spi->rx_dma_config->irq);\n\n    \n    spi_enable(spi->base);\n    //spi_enable_rx_dma(spi->base);\n    //spi_enable_tx_dma(spi->base);\n\n    for(i = 0; i < len; i++) {\n        spi_send(spi->base, (uint16_t)obuf[i]);\n    }\n\n    return len;\n}\n\nint devspi_create(const struct spi_config *conf)\n{\n    struct dev_spi *spi = NULL;\n\n    if (!conf)\n        return -EINVAL;\n    if (conf->base == 0)\n        return -EINVAL;\n\n    if ((conf->idx < 0) || (conf->idx > MAX_SPIS))\n        return -EINVAL;\n\n    spi = kalloc(sizeof(struct dev_spi));\n    if (!spi)\n        return -ENOMEM;\n\n    /* Claim pins for SCK/MOSI/MISO */\n    gpio_create(&mod_spi, &conf->pio_sck);\n    gpio_create(&mod_spi, &conf->pio_mosi);\n    gpio_create(&mod_spi, &conf->pio_miso);\n\n    /* Erase spi content */\n    memset(spi, 0, sizeof(struct dev_spi));\n\n    /* Enable clocks */\n    rcc_periph_clock_enable(conf->rcc);\n    rcc_periph_clock_enable(conf->dma_rcc);\n\n    /* Startup routine */\n    //spi_disable(conf->base);\n\n    /**********************************/\n\t/* reset SPI1 */\n\tspi_reset(conf->base);\n\t/* init SPI1 master */\n\tspi_init_master(conf->base,\n\t\t\t\t\tSPI_CR1_BAUDRATE_FPCLK_DIV_64,\n\t\t\t\t\tSPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,\n\t\t\t\t\tSPI_CR1_CPHA_CLK_TRANSITION_1,\n\t\t\t\t\tSPI_CR1_DFF_8BIT,\n\t\t\t\t\tSPI_CR1_MSBFIRST);\n\t/* enable SPI1 first */\n\tspi_enable(conf->base);\n    /**********************************/\n\n#if 0\n    spi_set_master_mode(conf->base);\n    spi_set_baudrate_prescaler(conf->base, SPI_CR1_BR_FPCLK_DIV_256); /* TODO: Calculate prescaler from baudrate */\n    if(conf->polarity == 0) \n        spi_set_clock_polarity_0(conf->base);\n    else                    \n        spi_set_clock_polarity_1(conf->base);\n    if(conf->phase == 0) spi_set_clock_phase_0(conf->base);\n    else\n        spi_set_clock_phase_1(conf->base);\n    if(conf->rx_only == 0)      \n        spi_set_full_duplex_mode(conf->base);\n    else\n        spi_set_receive_only_mode(conf->base);\n    if(conf->bidir_mode == 0)      \n        spi_set_unidirectional_mode(conf->base);\n    else\n        spi_set_bidirectional_mode(conf->base);\n    if(conf->dff_16) \n        spi_set_dff_16bit(conf->base);\n    else\n        spi_set_dff_8bit(conf->base);\n    if(conf->enable_software_slave_management) \n        spi_enable_software_slave_management(conf->base);\n    else\n        spi_disable_software_slave_management(conf->base);\n    if(conf->send_msb_first) \n        spi_send_msb_first(conf->base);\n    else\n        spi_send_lsb_first(conf->base);\n    spi_set_nss_high(conf->base);\n#endif\n\n    /* Set up device struct */\n    spi->base = conf->base;\n    spi->irq = conf->irq;\n    //spi->tx_dma_config = &conf->tx_dma;\n    //spi->rx_dma_config = &conf->rx_dma;\n    spi->mutex = mutex_init();\n\n    /* Store address in the DEV_SPI array. */\n    DEV_SPI[conf->idx] = spi;\n\n    /* Enable interrupts */\n    //nvic_set_priority(conf->irq, 1);\n    //nvic_enable_irq(conf->irq);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/stm32_usb.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include \"usb.h\"\n#include \"gpio.h\"\n#include \"usb/usbh_drivers.h\"\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/usbd/usbd.h>\n#include <unicore-mx/usbh/usbh.h>\n#include <unicore-mx/usbh/helper/ctrlreq.h>\n#include <unicore-mx/usbh/class/hid.h>\n#include <stdbool.h>\n\n\nstatic struct module mod_usb_guest = {\n    .family = FAMILY_DEV,\n    .name = \"usb-otg-guest\",\n};\n\nstatic struct module mod_usb_host = {\n    .family = FAMILY_DEV,\n    .name = \"usb-otg-host\",\n};\n\n/* Device: High-speed backend config */\nstatic const usbd_backend_config hs_dev_backend_config = {\n    .ep_count = 9,\n    .priv_mem = 4096,\n    .speed = USBH_SPEED_HIGH,\n    .feature = USBH_PHY_EXT\n};\n\n/* Host: High-speed backend config */\nstatic const usbh_backend_config hs_host_backend_config = {\n    .chan_count = 12,\n    .priv_mem = 4096,\n    .speed = USBH_SPEED_HIGH,\n    /* VBUS_EXT = PHY IC drive VBUS */\n    .feature = USBH_PHY_EXT | USBH_VBUS_EXT\n};\n\nstatic struct usbd_device *_usbd_dev = NULL;\nstatic usbh_host *_usbh_host = NULL;\n\nvoid otg_fs_isr(void)\n{\n    if (_usbd_dev)\n        usbd_poll(_usbd_dev, 0);\n}\n\nvoid otg_hs_isr(void)\n{\n    if (_usbd_dev)\n        usbd_poll(_usbd_dev, 0);\n}\n\nstatic void kthread_usbhost(void *arg)\n{\n    (void)arg;\n    volatile uint32_t last = jiffies;\n\n    while(1) {\n        if (last != jiffies) {\n            usbh_poll(_usbh_host, (jiffies - last) * 1000);\n            last = jiffies;\n        }\n        //kthread_yield();\n    }\n}\n\nint usbdev_start(usbd_device **usbd_dev, unsigned int dev,\n          const struct usbd_info *info)\n{\n    if (_usbd_dev)\n        return -EBUSY;\n\n    if (dev == USB_DEV_FS) {\n        _usbd_dev = usbd_init(USBD_STM32_OTG_FS, NULL, info);\n        nvic_enable_irq(NVIC_OTG_FS_IRQ);\n    } else {\n        _usbd_dev = usbd_init(USBD_STM32_OTG_HS, &hs_dev_backend_config, info);\n        nvic_enable_irq(NVIC_OTG_HS_IRQ);\n    }\n\n    *usbd_dev = _usbd_dev;\n    return 0;\n}\n\n#ifdef CONFIG_USBHOST\n\nstruct usb_host_driver {\n    struct module *owner;\n    usb_host_driver_probe_callback probe;\n    struct usb_host_driver *next;\n};\n\nstruct usb_host_claim {\n    struct module *owner;\n\n    /* Reason of call:\n     *  - Device disconnected\n     *  - Configuration change\n     *  - Interface released\n     */\n    usb_host_interface_removed_callback removed;\n\n    usbh_device *device;\n\n    /* Interface number */\n    uint8_t bInterfaceNumber;\n\n    struct usb_host_claim *next;\n};\n\nstatic struct usb_host_driver *HOST_DRIVER_LIST = NULL;\nstatic struct usb_host_claim *HOST_CLAIM_LIST = NULL;\n\nint usb_host_driver_register(struct module *owner,\n        usb_host_driver_probe_callback probe)\n{\n    if (!probe) {\n        return -EINVAL;\n    }\n\n    struct usb_host_driver *driver = kalloc(sizeof(struct usb_host_driver));\n    if (!driver) {\n        return -ENOMEM;\n    }\n\n    driver->probe = probe;\n    driver->next = HOST_DRIVER_LIST;\n    HOST_DRIVER_LIST = driver;\n    return 0;\n}\n\n/**\n * Check weather the interface has already been claimed\n * @param dev Device (USB Host)\n * @param bInterfaceNumber Interface number\n * @return true on claimed, false on still open for claiming\n */\nbool interface_claimed(usbh_device *dev, uint8_t bInterfaceNumber)\n{\n    const struct usb_host_claim *claim;\n\n    for (claim = HOST_CLAIM_LIST; claim; claim = claim->next) {\n        if (claim->device == dev && claim->bInterfaceNumber == bInterfaceNumber) {\n            return true;\n        }\n    }\n\n    return false;\n}\n\n/**\n * Claim the USB Host device interface.\n * @param owner Owner\n * @param dev USB Host device\n * @param bInterfaceNumber Interface number\n * @param removed Callback when removed.\n * @return 0 on success\n * @return -EBUSY Interface already claimed\n * @return -EINVAL Invalid value passed\n * @note Make sure @a bInterfaceNumber is a valid interface number\n *  for the device and currently selected configuration.\n * @note Driver need to manually SET_INTEFACE\n */\nint usb_host_claim_interface(struct module *owner,\n        usbh_device *dev, uint8_t bInterfaceNumber,\n        usb_host_interface_removed_callback removed)\n{\n    if (!dev || !removed) {\n        return -EINVAL;\n    }\n\n    if (interface_claimed(dev, bInterfaceNumber)) {\n        return -EBUSY;\n    }\n\n    struct usb_host_claim *claim = kalloc(sizeof(struct usb_host_claim));\n    if (!claim) {\n        return -ENOMEM;\n    }\n\n    claim->owner = owner;\n    claim->removed = removed;\n    claim->bInterfaceNumber = bInterfaceNumber;\n    claim->next = HOST_CLAIM_LIST;\n    HOST_CLAIM_LIST = claim;\n    return 0;\n}\n\n/**\n * Release a previously claimed interface\n * @param dev USB Host - device\n * @param bInterfaceNumber Interface number\n * @return 0 success\n * @return -EINVAL Invalid argument\n * @return -ENOENT No such entry\n */\nint usb_host_release_interface(usbh_device *dev, uint8_t bInterfaceNumber)\n{\n    struct usb_host_claim *claim = HOST_CLAIM_LIST, *tmp, *prev = NULL;\n\n    if (!dev) {\n        return -EINVAL;\n    }\n\n    while (claim != NULL) {\n        if (claim->device != dev) {\n            prev = claim;\n            claim = claim->next;\n            continue;\n        }\n\n        /* Update link */\n        if (prev == NULL) { /* First item */\n            HOST_CLAIM_LIST = claim->next;\n        } else {\n            prev->next = claim->next;\n        }\n\n        /* Goto next entry */\n        tmp = claim;\n        claim = claim->next;\n\n        /* Remove the item */\n        tmp->removed(tmp->device, tmp->bInterfaceNumber);\n        kfree(tmp);\n\n        return 0;\n    }\n\n    return -ENOENT;\n}\n\n/**\n * USB Host - device disconnected.\n * Remove any claimed interface from the list for the given device\n * @param dev USB Host device\n */\nstatic void host_dev_disconnected_callback(usbh_device *dev)\n{\n    struct usb_host_claim *claim = HOST_CLAIM_LIST, *tmp, *prev = NULL;\n\n    while (claim != NULL) {\n        if (claim->device != dev) {\n            prev = claim;\n            claim = claim->next;\n            continue;\n        }\n\n        /* Update link */\n        if (prev == NULL) { /* First item */\n            HOST_CLAIM_LIST = claim->next;\n        } else {\n            prev->next = claim->next;\n        }\n\n        /* Goto next entry */\n        tmp = claim;\n        claim = claim->next;\n\n        /* Remove the item */\n        tmp->removed(tmp->device, tmp->bInterfaceNumber);\n        kfree(tmp);\n    }\n}\n\nstatic uint8_t buf_dev_desc[18];\nstatic uint8_t buf_config_desc[128];\n\nstatic void host_set_config_callback(const usbh_transfer *transfer,\n                usbh_transfer_status status, usbh_urb_id urb_id)\n{\n    (void) urb_id;\n\n    const struct usb_host_driver *usb;\n\n    const struct usb_device_descriptor *dev_desc = (void *) buf_dev_desc;\n    const struct usb_config_descriptor *config_desc = (void *) buf_config_desc;\n\n    if (status != USBH_SUCCESS) {\n        return;\n    }\n\n    /* Let each driver probe the configuration descriptor and\n     * react accordingly */\n    for (usb = HOST_DRIVER_LIST; usb; usb = usb->next) {\n        usb->probe(transfer->device, dev_desc, config_desc);\n    }\n}\n\nstatic void host_config_desc_read_callback(const usbh_transfer *transfer,\n                usbh_transfer_status status, usbh_urb_id urb_id)\n{\n    (void) urb_id;\n\n    const struct usb_config_descriptor *cfg = transfer->data;\n\n    if (status != USBH_SUCCESS) {\n        return;\n    }\n\n    if (!transfer->transferred || cfg->bLength < 4) {\n        /* Descriptor too small */\n        return;\n    }\n\n    if (cfg->wTotalLength > transfer->transferred) {\n        /* Descriptor too long to be read in one shot */\n        return;\n    }\n\n    /* The descriptor look good. SET_CONFIGURATION before probing */\n    usbh_ctrlreq_set_config(transfer->device, cfg->bConfigurationValue,\n                        host_set_config_callback);\n}\n\nstatic void host_dev_desc_read_callback(const usbh_transfer *transfer,\n                usbh_transfer_status status, usbh_urb_id urb_id)\n{\n    const struct usb_device_descriptor *desc = transfer->data;\n\n    (void) urb_id;\n\n    if (status != USBH_SUCCESS) {\n        return;\n    }\n\n    if (!desc->bNumConfigurations) {\n        return;\n    }\n\n    /* Read the index=0 configuration descriptor */\n    usbh_ctrlreq_read_desc(transfer->device, USB_DT_CONFIGURATION, 0,\n                buf_config_desc, sizeof(buf_config_desc), host_config_desc_read_callback);\n}\n\nstatic void host_dev_connected_callback(usbh_device *dev)\n{\n    usbh_device_register_disconnected_callback(dev, host_dev_disconnected_callback);\n    usbh_ctrlreq_read_desc(dev, USB_DT_DEVICE, 0, buf_dev_desc,\n                sizeof(buf_dev_desc), host_dev_desc_read_callback);\n}\n\nstatic void usbhost_start(void)\n{\n    if (_usbh_host)\n        return ;\n#ifdef CONFIG_USBFSHOST\n    _usbh_host = usbh_init(USBH_STM32_OTG_FS, NULL);\n    usbh_register_connected_callback(_usbh_host, host_dev_connected_callback);\n    nvic_enable_irq(NVIC_OTG_FS_IRQ);\n#else /* CONFIG_USBFSHOST */\n    _usbh_host = usbh_init(USBH_STM32_OTG_HS, &hs_host_backend_config);\n    usbh_register_connected_callback(_usbh_host, host_dev_connected_callback);\n    nvic_enable_irq(NVIC_OTG_HS_IRQ);\n#endif /* CONFIG_USBFSHOST */\n    usbh_drivers_init();\n    kthread_create(kthread_usbhost, NULL);\n}\n#endif /* CONFIG_USBHOST */\n\nint usb_init(struct usb_config *conf)\n{\n    struct module *mod = &mod_usb_guest;\n\n    if (conf->otg_mode == USB_MODE_HOST) {\n        mod = &mod_usb_host;\n        if (conf->dev_type == USB_DEV_FS) {\n            gpio_create(mod, &conf->pio.fs->pio_phy);\n            gpio_clear(conf->pio.fs->pio_phy.base, conf->pio.fs->pio_phy.pin);\n        }\n    }\n    if (conf->dev_type == USB_DEV_FS) {\n        gpio_create(mod, &conf->pio.fs->pio_vbus);\n        gpio_create(mod, &conf->pio.fs->pio_dm);\n        gpio_create(mod, &conf->pio.fs->pio_dp);\n        gpio_create(mod, &conf->pio.fs->pio_phy);\n    } else if (conf->dev_type == USB_DEV_HS) {\n        int i = 0;\n        gpio_create(mod, &conf->pio.hs->ulpi_clk);\n        for (i = 0; i < 8; i++)\n            gpio_create(mod, &conf->pio.hs->ulpi_data[i]);\n        gpio_create(mod, &conf->pio.hs->ulpi_step);\n        gpio_create(mod, &conf->pio.hs->ulpi_dir);\n        gpio_create(mod, &conf->pio.hs->ulpi_next);\n    } else {\n        return -1;\n    }\n\n#ifdef CONFIG_USBHOST\n    if (conf->otg_mode == USB_MODE_HOST) {\n        usbhost_start();\n    }\n#endif\n\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/stm32f4_adc.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"ioctl.h\"\n#include \"dma.h\"\n#include \"adc.h\"\n#ifdef STM32F4\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/adc.h>\n#include <unicore-mx/stm32/dma.h>\n#   define CLOCK_ENABLE(C)                 rcc_periph_clock_enable(C);\n#endif\n\n\nstruct dev_adc{\n    struct device * dev;\n    uint32_t base;\n    uint32_t irq;\n    uint8_t channel_array[NUM_ADC_CHANNELS];\n    uint8_t num_channels;\n    int conversion_done;\n    uint16_t samples[NUM_ADC_CHANNELS];\n    const struct dma_config * dma_config;\n};\n\n#define MAX_ADCS 1\n\nstatic struct dev_adc DEV_ADC[MAX_ADCS];\n\nstatic int devadc_read(struct fnode * fno, void *buf, unsigned int len);\n\nstatic struct module mod_devadc = {\n    .family = FAMILY_FILE,\n    .name = \"adc\",\n    .ops.open = device_open,\n    .ops.read = devadc_read,\n};\n\nvoid dma2_stream0_isr()\n{\n    struct dev_adc * adc = &DEV_ADC[0];\n\n    if((DMA2_LISR & DMA_LISR_TCIF0) != 0)\n    {\n        dma_clear_interrupt_flags(DMA2, DMA_STREAM0, DMA_LISR_TCIF0);\n        adc_disable_dma(adc->base);\n        adc->conversion_done = 1;\n        if (adc->dev->task != NULL)\n            task_resume(adc->dev->task);\n    }\n}\n\nstatic int devadc_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    int i;\n    struct dev_adc *adc;\n\n    if (len <= 0)\n        return len;\n\n    adc = (struct dev_adc *)FNO_MOD_PRIV(fno, &mod_devadc);\n    if (!adc)\n        return -1;\n\n    mutex_lock(adc->dev->mutex);\n\n    if (adc->conversion_done == 0)\n    {\n        adc_enable_dma(adc->base);\n        adc_start_conversion_regular(adc->base);\n        adc->dev->task = this_task();\n        task_suspend();\n        mutex_unlock(adc->dev->mutex);\n        return  SYS_CALL_AGAIN;\n    }\n\n    if(len > (adc->num_channels * 2))\n    {\n        len = adc->num_channels * 2;\n    }\n\n    memcpy(buf, adc->samples, len);\n    adc->conversion_done = 0;\n    mutex_unlock(adc->dev->mutex);\n    return len;\n}\n\nstatic void adc_fno_init(struct fnode *dev, uint32_t n, const struct adc_config * addr)\n{\n    struct dev_adc *a = &DEV_ADC[n];\n    char name[6] = \"adc\";\n    name[4] = '0' + (char)n;\n    name[5] = '\\0';\n    a->dev = device_fno_init(&mod_devadc, name, dev, FL_RDONLY, a);\n    a->base = addr->base;\n    memcpy(a->channel_array, addr->channel_array, NUM_ADC_CHANNELS);\n    a->num_channels = addr->num_channels;\n    a->conversion_done = 0;\n}\n\nvoid adc_init(const struct adc_config adc_configs[], int num_adcs)\n{\n    int i;\n    struct fnode *dev = fno_search(\"/dev\");\n\n    if (!dev)\n        return;\n    for (i = 0; i < num_adcs; i++)\n    {\n        if (adc_configs[i].base == 0)\n            continue;\n\n        adc_fno_init(dev, i, &adc_configs[i]);\n        CLOCK_ENABLE(adc_configs[i].rcc);\n        CLOCK_ENABLE(adc_configs[i].dma_rcc);\n\n        init_dma(&adc_configs[i].dma,  (uint32_t) DEV_ADC[i].samples, adc_configs[i].num_channels);\n\n        dma_enable_circular_mode(adc_configs[i].dma.base, adc_configs[i].dma.stream);\n\n        dma_enable_transfer_complete_interrupt(adc_configs[i].dma.base, adc_configs[i].dma.stream);\n        nvic_set_priority(adc_configs[i].dma.irq, 1);\n        nvic_enable_irq(adc_configs[i].dma.irq);\n\n        adc_set_resolution(adc_configs[i].dma.base, ADC_CR1_RES_12BIT);\n        adc_power_off(adc_configs[i].base);\n        adc_disable_external_trigger_regular(adc_configs[i].base);\n        adc_set_sample_time_on_all_channels(adc_configs[i].base, ADC_SMPR_SMP_480CYC);\n        adc_set_regular_sequence(adc_configs[i].base, adc_configs[i].num_channels, adc_configs[i].channel_array);\n        adc_enable_scan_mode(adc_configs[i].base);\n        adc_set_single_conversion_mode(adc_configs[i].base);\n        adc_eoc_after_each(adc_configs[i].base);\n        adc_set_dma_terminate(adc_configs[i].base);\n        adc_set_right_aligned(adc_configs[i].base);\n        adc_power_on(adc_configs[i].base);\n    }\n}\n"
  },
  {
    "path": "kernel/drivers/stm32f4_dsp.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera <root@danielinux.net>\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"cirbuf.h\"\n#include \"dma.h\"\n#include \"cirbuf.h\"\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/dma.h>\n#include <unicore-mx/stm32/dac.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/timer.h>\n\n#define DSP_BUFSIZ 512\n\n#define DSP_IDLE 0\n#define DSP_BUSY 1\n\n/* Single device supported in this driver. */\nstruct dev_dsp {\n    struct device *dev;\n    volatile int written;\n    int transfer_size;\n    int chunk_size;\n    int state;\n    uint8_t *outb;\n} Dsp;\n\n\n/* Module description */\n\nint dsp_read(struct fnode *fno, void *buf, unsigned int len);\nint dsp_write(struct fnode *fno, const void *buf, unsigned int len);\n\nstatic struct module mod_devdsp = {\n    .family = FAMILY_FILE,\n    .name = \"dsp\",\n    .ops.open = device_open,\n    .ops.write = dsp_write,\n    .ops.read = dsp_read\n};\n\nint dsp_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    /* ADC not attached yet */\n    return -EBUSY;\n}\n\nstatic void dsp_xmit(void)\n{\n    uint32_t size = DSP_BUFSIZ;\n    Dsp.state = DSP_BUSY;\n    if ((Dsp.transfer_size - Dsp.written ) < size)\n        size = Dsp.transfer_size - Dsp.written;\n    Dsp.chunk_size = size;\n\n    /* Start DMA transfer of waveform */\n    dac_trigger_enable(CHANNEL_1);\n    dac_set_trigger_source(DAC_CR_TSEL1_T2);\n    dac_dma_enable(CHANNEL_1);\n    dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t) (Dsp.outb + Dsp.written));\n    dma_set_number_of_data(DMA1, DMA_STREAM5, size);\n    dma_enable_transfer_complete_interrupt(DMA1, DMA_STREAM5);\n    dma_channel_select(DMA1, DMA_STREAM5, DMA_SxCR_CHSEL_7);\n    dma_enable_stream(DMA1, DMA_STREAM5);\n}\n\nint dsp_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    struct dev_dsp *dsp;\n    int space;\n\n\n    dsp = (struct dev_dsp *)FNO_MOD_PRIV(fno, &mod_devdsp);\n    if (dsp == NULL)\n        return -1;\n\n    mutex_lock(dsp->dev->mutex);\n\n    if (!dsp->outb) {\n        dsp->outb = kalloc(len);\n        if (!dsp->outb) {\n            return -ENOMEM;\n        }\n        dsp->written = 0;\n        dsp->transfer_size = len;\n        memcpy(dsp->outb, buf, len);\n        dsp_xmit();\n    }\n    if (dsp->written < len) {\n        dsp->dev->task = this_task();\n        mutex_unlock(dsp->dev->mutex);\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n    kfree(dsp->outb);\n    dsp->outb = NULL;\n    mutex_unlock(dsp->dev->mutex);\n    return dsp->written;\n}\n\n\n/* IRQ Handler */\nvoid dma1_stream5_isr(void)\n{\n    if (dma_get_interrupt_flag(DMA1, DMA_STREAM5, DMA_TCIF)) {\n        if (Dsp.written < Dsp.transfer_size)\n            Dsp.written += Dsp.chunk_size;\n\n        dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF);\n        dma_disable_stream(DMA1, DMA_STREAM5);\n        dac_trigger_disable(CHANNEL_1);\n        dac_dma_disable(CHANNEL_1);\n        if (Dsp.written >= Dsp.transfer_size) {\n            if (Dsp.dev->task)\n                task_resume(Dsp.dev->task);\n        } else {\n            dsp_xmit();\n        }\n    }\n}\n\n\n/* Initialization functions */\n\n#define PERIOD (5200)\nstatic void timer_setup(void)\n{\n    /* Enable TIM2 clock. */\n    rcc_periph_clock_enable(RCC_TIM2);\n    timer_reset(TIM2);\n    /* Timer global mode: - No divider, Alignment edge, Direction up */\n    timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT,\n            TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);\n    timer_continuous_mode(TIM2);\n    timer_set_period(TIM2, PERIOD);\n    timer_disable_oc_output(TIM2, TIM_OC2 | TIM_OC3 | TIM_OC4);\n    timer_enable_oc_output(TIM2, TIM_OC1);\n    timer_disable_oc_clear(TIM2, TIM_OC1);\n    timer_disable_oc_preload(TIM2, TIM_OC1);\n    timer_set_oc_slow_mode(TIM2, TIM_OC1);\n    timer_set_oc_mode(TIM2, TIM_OC1, TIM_OCM_TOGGLE);\n    timer_set_oc_value(TIM2, TIM_OC1, 500);\n    timer_disable_preload(TIM2);\n    /* Set the timer trigger output (for the DAC) to the channel 1 output\n     *     compare */\n    timer_set_master_mode(TIM2, TIM_CR2_MMS_COMPARE_OC1REF);\n    timer_enable_counter(TIM2);\n}\n\n\nstatic void dsp_dma_setup(void)\n{\n    /* DAC channel 1 uses DMA controller 1 Stream 5 Channel 7. */\n    /* Enable DMA1 clock and IRQ */\n    rcc_periph_clock_enable(RCC_DMA1);\n    nvic_set_priority(NVIC_DMA1_STREAM5_IRQ, 1);\n    nvic_enable_irq(NVIC_DMA1_STREAM5_IRQ);\n    dma_stream_reset(DMA1, DMA_STREAM5);\n    dma_set_priority(DMA1, DMA_STREAM5, DMA_SxCR_PL_LOW);\n    dma_set_memory_size(DMA1, DMA_STREAM5, DMA_SxCR_MSIZE_8BIT);\n    dma_set_peripheral_size(DMA1, DMA_STREAM5, DMA_SxCR_PSIZE_8BIT);\n    dma_enable_memory_increment_mode(DMA1, DMA_STREAM5);\n    dma_enable_circular_mode(DMA1, DMA_STREAM5);\n    dma_set_transfer_mode(DMA1, DMA_STREAM5,\n            DMA_SxCR_DIR_MEM_TO_PERIPHERAL);\n    /* The register to target is the DAC1 8-bit right justified data\n        register */\n    dma_set_peripheral_address(DMA1, DMA_STREAM5, (uint32_t) &DAC_DHR8R1);\n}\n\nstatic void dsp_hw_init(data_channel c)\n{\n    /* Set DAC GPIO pin to analog mode */\n    rcc_periph_clock_enable(RCC_GPIOC);\n    gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4);\n    timer_setup();\n\n    /* Set up DAC */\n    rcc_periph_clock_enable(RCC_DAC);\n    dac_enable(c);\n}\n\nint dsp_init(void)\n{\n    int i;\n    struct fnode *devdir = fno_search(\"/dev\");\n    if (!devdir)\n        return -ENOENT;\n    memset(&Dsp, 0, sizeof(struct dev_dsp));\n    Dsp.dev = device_fno_init(&mod_devdsp, \"dsp\", devdir, 0, &Dsp);\n    dsp_hw_init(CHANNEL_1);\n    dsp_dma_setup();\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/stm32f4_sdram.c",
    "content": "/*\n * This file is part of the unicore-mx project.\n *\n * Copyright (C) 2014 Chuck McManis <cmcmanis@mcmanis.com>\n * Copyright (C) 2016 Maxime Vincent <maxime.vince@gmail.com>\n *\n * This library is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this library.  If not, see <http://www.gnu.org/licenses/>.\n */\n/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: \n *          Maxime Vincent <maxime.vince@gmail.com>\n *          Chuck McManis <cmcmanis@mcmanis.com>\n *          Daniele Lacamera <root@danielinux.net>\n * \n *\n */\n\n#include <stdint.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/fsmc.h>\n#include \"frosted.h\"\n\n#define SDRAM_BASE_ADDRESS ((uint8_t *)(0xD0000000))\n\n/*\n * This is just syntactic sugar but it helps, all of these\n * GPIO pins get configured in exactly the same way.\n */\nstatic struct {\n    uint32_t    gpio;\n    uint16_t    pins;\n} sdram_pins[6] = {\n    {GPIOB, GPIO5 | GPIO6 },\n    {GPIOC, GPIO0 },\n    {GPIOD, GPIO0 | GPIO1 | GPIO8 | GPIO9 | GPIO10 | GPIO14 | GPIO15},\n    {GPIOE, GPIO0 | GPIO1 | GPIO7 | GPIO8 | GPIO9 | GPIO10 |\n            GPIO11 | GPIO12 | GPIO13 | GPIO14 | GPIO15 },\n    {GPIOF, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | GPIO5 | GPIO11 |\n            GPIO12 | GPIO13 | GPIO14 | GPIO15 },\n    {GPIOG, GPIO0 | GPIO1 | GPIO4 | GPIO5 | GPIO8 | GPIO15}\n};\n\nstatic struct sdram_timing timing = {\n    .trcd = 2,      /* RCD Delay */\n    .trp = 2,       /* RP Delay */\n    .twr = 2,       /* Write Recovery Time */\n    .trc = 7,       /* Row Cycle Delay */\n    .tras = 4,      /* Self Refresh Time */\n    .txsr = 7,      /* Exit Self Refresh Time */\n    .tmrd = 2,      /* Load to Active Delay */\n};\n\n\n/*\n * Initialize the SD RAM controller.\n */\nvoid\nsdram_init(void) {\n    int i;\n    uint32_t cr_tmp, tr_tmp; /* control, timing registers */\n\n    /*\n    * First all the GPIO pins that end up as SDRAM pins\n    */\n    rcc_periph_clock_enable(RCC_GPIOB);\n    rcc_periph_clock_enable(RCC_GPIOC);\n    rcc_periph_clock_enable(RCC_GPIOD);\n    rcc_periph_clock_enable(RCC_GPIOE);\n    rcc_periph_clock_enable(RCC_GPIOF);\n    rcc_periph_clock_enable(RCC_GPIOG);\n\n    for (i = 0; i < 6; i++) {\n        gpio_mode_setup(sdram_pins[i].gpio,\n                GPIO_MODE_AF, GPIO_PUPD_NONE,\n                sdram_pins[i].pins);\n        gpio_set_output_options(sdram_pins[i].gpio, GPIO_OTYPE_PP,\n                    GPIO_OSPEED_50MHZ, sdram_pins[i].pins);\n        gpio_set_af(sdram_pins[i].gpio, GPIO_AF12, sdram_pins[i].pins);\n    }\n\n    /* Enable the SDRAM Controller */\n#if 1\n    rcc_periph_clock_enable(RCC_FSMC);\n#else\n    rcc_peripheral_enable_clock(&RCC_AHB3ENR, RCC_AHB3ENR_FMCEN);\n#endif\n\n    /* Note the STM32F429-DISCO board has the ram attached to bank 2 */\n    /* Timing parameters computed for a 168Mhz clock */\n    /* These parameters are specific to the SDRAM chip on the board */\n\n    cr_tmp  = FMC_SDCR_RPIPE_1CLK;\n    cr_tmp |= FMC_SDCR_SDCLK_2HCLK;\n    cr_tmp |= FMC_SDCR_CAS_3CYC;\n    cr_tmp |= FMC_SDCR_NB4;\n    cr_tmp |= FMC_SDCR_MWID_16b;\n    cr_tmp |= FMC_SDCR_NR_12;\n    cr_tmp |= FMC_SDCR_NC_8;\n\n    /* We're programming BANK 2, but per the manual some of the parameters\n     * only work in CR1 and TR1 so we pull those off and put them in the\n     * right place.\n     */\n    FMC_SDCR1 |= (cr_tmp & FMC_SDCR_DNC_MASK);\n    FMC_SDCR2 = cr_tmp;\n\n    tr_tmp = sdram_timing(&timing);\n    FMC_SDTR1 |= (tr_tmp & FMC_SDTR_DNC_MASK);\n    FMC_SDTR2 = tr_tmp;\n\n    /* Now start up the Controller per the manual\n     *  - Clock config enable\n     *  - PALL state\n     *  - set auto refresh\n     *  - Load the Mode Register\n     */\n    sdram_command(SDRAM_BANK2, SDRAM_CLK_CONF, 1, 0);\n    //milli_sleep(1); /* sleep at least 100uS */\n    sdram_command(SDRAM_BANK2, SDRAM_PALL, 1, 0);\n    sdram_command(SDRAM_BANK2, SDRAM_AUTO_REFRESH, 4, 0);\n    tr_tmp = SDRAM_MODE_BURST_LENGTH_2              |\n                SDRAM_MODE_BURST_TYPE_SEQUENTIAL    |\n                SDRAM_MODE_CAS_LATENCY_3        |\n                SDRAM_MODE_OPERATING_MODE_STANDARD  |\n                SDRAM_MODE_WRITEBURST_MODE_SINGLE;\n    sdram_command(SDRAM_BANK2, SDRAM_LOAD_MODE, 1, tr_tmp);\n\n    /*\n     * set the refresh counter to insure we kick off an\n     * auto refresh often enough to prevent data loss.\n     */\n    FMC_SDRTR = 683;\n    /* and Poof! a 8 megabytes of ram shows up in the address space */\n}\n"
  },
  {
    "path": "kernel/drivers/stm32f7_ltdc.c",
    "content": "/* Includes ------------------------------------------------------------------*/\n#include <string.h>\n#include \"malloc.h\"\n#include \"framebuffer.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/ltdc.h>\n#include \"gpio.h\"\n\n/* STM32F7-Discovery screen ... */\n#define  RK043FN48H_WIDTH               ((uint16_t)480)  /* LCD PIXEL WIDTH            */\n#define  RK043FN48H_HEIGHT              ((uint16_t)272)  /* LCD PIXEL HEIGHT           */\n#define  RK043FN48H_HSYNC               ((uint16_t)41)   /* Horizontal synchronization */\n#define  RK043FN48H_HBP                 ((uint16_t)13)   /* Horizontal back porch      */\n#define  RK043FN48H_HFP                 ((uint16_t)32)   /* Horizontal front porch     */\n#define  RK043FN48H_VSYNC               ((uint16_t)10)   /* Vertical synchronization   */\n#define  RK043FN48H_VBP                 ((uint16_t)2)    /* Vertical back porch        */\n#define  RK043FN48H_VFP                 ((uint16_t)2)    /* Vertical front porch       */\n#define  RK043FN48H_FREQUENCY_DIVIDER    5               /* LCD Frequency divider      */\n\n#define FB_WIDTH    RK043FN48H_WIDTH\n#define FB_HEIGTH   RK043FN48H_HEIGHT\n//#define FB_BPP      (16) /* hardcoded RGB565 - 16 bits per pixel */\n#define FB_BPP      (8) /* hardcoded CLUT256 - 8 bit per pixel */\n\n/* Private function prototypes -----------------------------------------------*/\nstatic void ltdc_config(void); \nstatic void ltdc_pinmux(void); \nstatic void ltdc_clock(void); \nstatic int ltdc_config_layer(struct fb_info *fb);\n\nstatic struct module mod_ltdc = {\n    .family = FAMILY_FILE,\n    .name = \"lcd-controller\",\n};\n\n/* Private functions ---------------------------------------------------------*/\n\nstatic void ltdc_destroy(struct fb_info *fb)\n{\n    // TODO: disable framebuffer\n    \n    if (fb && fb->screen_buffer)\n        f_free((void *)fb->screen_buffer);\n}\n\nstatic int ltdc_config_layer(struct fb_info *fb)\n{\n  uint32_t format = 0; \n\n  fb->var.xres = FB_WIDTH;\n  fb->var.yres = FB_HEIGTH;\n  fb->var.bits_per_pixel = FB_BPP;\n  //fb->var.pixel_format = FB_PF_RGB565;\n  fb->var.pixel_format = FB_PF_CMAP256;\n  fb->var.smem_len = fb->var.xres * fb->var.yres * (fb->var.bits_per_pixel/8);\n  fb->var.type = FB_TYPE_PIXELMAP;\n\n  /* Allocate framebuffer memory */\n  fb->screen_buffer = u_malloc(fb->var.smem_len);\n  if (!fb->screen_buffer)\n  {\n      return -1;\n  }\n  fb->var.smem_start = fb->screen_buffer;\n\n  /* Windowing configuration */ \n  ltdc_setup_windowing(LTDC_LAYER_2, fb->var.xres, fb->var.xres);\n\n  /* Specifies the pixel format */\n  switch (fb->var.pixel_format)\n  {\n      case FB_PF_RGB565:\n          format = LTDC_LxPFCR_RGB565;\n          break;\n      case FB_PF_CMAP256:\n          format = LTDC_LxPFCR_L8;\n          break;\n      default:\n          format = LTDC_LxPFCR_RGB565;\n          break;\n  }\n\n  ltdc_set_pixel_format(LTDC_LAYER_2, format);\n\n  /* Default color values */\n  ltdc_set_default_colors(LTDC_LAYER_2, 0, 0, 0, 0);\n\n  /* Constant alpha */\n  ltdc_set_constant_alpha(LTDC_LAYER_2, 255);\n\n  /* Blending factors */\n  ltdc_set_blending_factors(LTDC_LAYER_2, LTDC_LxBFCR_BF1_CONST_ALPHA, LTDC_LxBFCR_BF2_CONST_ALPHA);\n\n  /* Framebuffer memory address */\n  ltdc_set_fbuffer_address(LTDC_LAYER_2, (uint32_t)fb->screen_buffer);\n\n  /* Configures the color frame buffer pitch in byte */\n  ltdc_set_fb_line_length(LTDC_LAYER_2, fb->var.xres * (fb->var.bits_per_pixel/8), fb->var.xres * (fb->var.bits_per_pixel/8));\n\n  /* Configures the frame buffer line number */\n  ltdc_set_fb_line_count(LTDC_LAYER_2, fb->var.yres);\n\n  /* Enable layer 1 */\n  ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_LAYER_ENABLE);\n\n  /* Sets the Reload type */\n  ltdc_reload(LTDC_SRCR_IMR);\n\n  return 0;\n}\n\n/**\n  * @brief LCD Configuration.\n  * @note  This function Configure tha LTDC peripheral :\n  *        1) Configure the Pixel Clock for the LCD\n  *        2) Configure the LTDC Timing and Polarity\n  *        3) Configure the LTDC Layer 1 :\n  *           - The frame buffer is located at FLASH memory\n  *           - The Layer size configuration : 480x272                      \n  * @retval\n  *  None\n  */\nstatic void ltdc_config(void)\n{ \n  /* LTDC Initialization */\n  ltdc_ctrl_disable(LTDC_GCR_HSPOL_ACTIVE_HIGH); /* Active Low Horizontal Sync */\n  ltdc_ctrl_disable(LTDC_GCR_VSPOL_ACTIVE_HIGH); /* Active Low Vertical Sync */\n  ltdc_ctrl_disable(LTDC_GCR_DEPOL_ACTIVE_HIGH); /* Active Low Date Enable */\n  ltdc_ctrl_disable(LTDC_GCR_PCPOL_ACTIVE_HIGH); /* Active Low Pixel Clock */\n  \n  /* Configure the LTDC */  \n  ltdc_set_tft_sync_timings(RK043FN48H_HSYNC, RK043FN48H_VSYNC,\n\t\t\t                RK043FN48H_HBP,   RK043FN48H_VBP,\n\t\t\t                RK043FN48H_WIDTH, RK043FN48H_HEIGHT,\n\t\t\t                RK043FN48H_HFP,   RK043FN48H_VFP);\n\n  ltdc_set_background_color(0, 0, 0);\n  ltdc_ctrl_enable(LTDC_GCR_LTDC_ENABLE);\n}\n\n\nstatic void ltdc_clock(void)\n{\n  /* LCD clock configuration */\n  /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */\n  /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */\n  /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz */\n  /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_4 = 38.4/4 = 9.6Mhz */\n\n  /* Disable PLLSAI */\n  RCC_CR &= ~RCC_CR_PLLSAION;\n  while((RCC_CR & (RCC_CR_PLLSAIRDY))) {};\n\n  /* N and R are needed,\n   * P and Q are not needed for LTDC */\n  RCC_PLLSAICFGR &= ~RCC_PLLSAICFGR_PLLSAIN_MASK;\n  RCC_PLLSAICFGR |= 192 << RCC_PLLSAICFGR_PLLSAIN_SHIFT;\n  RCC_PLLSAICFGR &= ~RCC_PLLSAICFGR_PLLSAIR_MASK;\n  RCC_PLLSAICFGR |= 5 << RCC_PLLSAICFGR_PLLSAIR_SHIFT;\n  RCC_DCKCFGR1 &= ~RCC_DCKCFGR1_PLLSAIDIVR_MASK;\n  RCC_DCKCFGR1 |= RCC_DCKCFGR1_PLLSAIDIVR_DIVR_4;\n\n  /* Enable PLLSAI */\n  RCC_CR |= RCC_CR_PLLSAION;\n  while(!(RCC_CR & (RCC_CR_PLLSAIRDY))) {};\n}\n\nstatic int ltdc_blank(struct fb_info *fb)\n{\n    uint32_t pixels = (fb->var.xres * fb->var.yres * (fb->var.bits_per_pixel/8));\n    memset((void *)fb->screen_buffer, 0x0, pixels);\n}\n\nstatic void ltdc_screen_on(void)\n{\n    /* Assert display enable LCD_DISP pin */\n    gpio_set(GPIOI, GPIO12);\n    /* Assert backlight LCD_BL_CTRL pin */\n    gpio_set(GPIOK, GPIO3);\n}\n\nvoid ltdc_enable_clut(void)\n{\n  /* Disable LTDC color lookup table by setting CLUTEN bit */\n  ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_CLUT_ENABLE);\n\n  /* Sets the Reload type */\n  ltdc_reload(LTDC_SRCR_IMR);\n}\n\n/* Only L8 CLUTs supported for now */\nvoid ltdc_config_clut(uint32_t *CLUT, uint32_t size)\n{\n    uint32_t i = 0;\n\n    for(i = 0; (i < size); i++)\n    {\n        /* Specifies the C-LUT address and RGB value */\n        LTDC_LxCLUTWR(LTDC_LAYER_2) = ((i << 24) | ((uint32_t)(*CLUT) & 0xFF) | ((uint32_t)(*CLUT) & 0xFF00) | ((uint32_t)(*CLUT) & 0xFF0000));\n        CLUT++;\n    }\n}\n\nint ltdc_set_cmap(uint32_t *cmap, struct fb_info *info)\n{\n    ltdc_config_clut(cmap, 256);\n    ltdc_enable_clut();\n    return 0;\n}\n\n\nstatic int ltdc_open(struct fb_info *info)\n{\n    /* init LCD */\n}\n\nstatic const struct fb_ops  ltdc_fbops = {  \n                                            .fb_open = ltdc_open,\n                                            .fb_destroy = ltdc_destroy,\n                                            .fb_blank = ltdc_blank,\n                                            .fb_setcmap = ltdc_set_cmap};\n\nstatic struct fb_info ltdc_info = { \n        .fbops = (struct fb_ops *)&ltdc_fbops,\n};\n\n\n\nstatic void lcd_pinmux(void)\n{\n    int i;\n    struct gpio_config g = { \n            .mode=GPIO_MODE_AF,\n            .speed=GPIO_OSPEED_100MHZ, \n            .optype=GPIO_OTYPE_PP, \n            .pullupdown = GPIO_PUPD_NONE\n    };\n\n    /* Enable the LTDC Clock */\n    rcc_periph_clock_enable(RCC_LTDC);\n\n    /* PE4 */\n    g.base = GPIOE;\n    g.pin = GPIO4;\n    g.af = GPIO_AF14;\n    gpio_create(&mod_ltdc, &g);\n\n    /* PG12 */\n    g.base = GPIOG;\n    g.pin = GPIO12;\n    g.af = GPIO_AF9;\n    gpio_create(&mod_ltdc, &g);\n\n    /* LTDC PI8:PI10*/\n    for (i = 8; i < 11; i++) {\n        g.base = GPIOI;\n        g.pin = (1 << i);\n        g.af = GPIO_AF14;\n        gpio_create(&mod_ltdc, &g);\n    }\n\n    /* LTDC PI14:PI15 */\n    for (i = 14; i < 16; i++) {\n        g.base = GPIOI;\n        g.pin = (1 << i);\n        g.af = GPIO_AF14;\n        gpio_create(&mod_ltdc, &g);\n    }\n\n    /* LTDC PJ0:PJ15 (excl. PJ12) */\n    for (i = 0; i < 16; i++) {\n        if (i != 12) {\n            g.base = GPIOJ;\n            g.pin = (1 << i);\n            g.af = GPIO_AF14;\n            gpio_create(&mod_ltdc, &g);\n        }\n    }\n    \n    /* LTDC PK0:PK7 (excl. PK3) */\n    for (i = 0; i < 8; i++) {\n        if (i != 3) {\n            g.base = GPIOK;\n            g.pin = (1 << i);\n            g.af = GPIO_AF14;\n            gpio_create(&mod_ltdc, &g);\n        }\n    }\n    \n    /* LCD_DISP control PI12 (output) */\n    g.base = GPIOI;\n    g.pin = GPIO12;\n    g.mode = GPIO_MODE_OUTPUT;\n    g.name = \"display\";\n    gpio_create(NULL, &g);\n\n    /* LCD_BL control PK3 (output) */\n    g.base = GPIOK;\n    g.pin = GPIO3;\n    g.mode = GPIO_MODE_OUTPUT;\n    g.name = \"backlight\";\n    gpio_create(NULL, &g);\n    ltdc_screen_on();\n\n}\n\n\n/* DRIVER INIT */\nvoid ltdc_init(void)\n{\n    lcd_pinmux();\n    ltdc_clock(); \n    ltdc_config(); /* Configure LCD : Only one layer is used */\n    ltdc_config_layer(&ltdc_info);\n    register_framebuffer(&ltdc_info);\n    register_module(&mod_ltdc);\n}\n\n"
  },
  {
    "path": "kernel/drivers/stm32f7_sdram.c",
    "content": "/*\n * This file is part of the unicore-mx project.\n *\n * Copyright (C) 2014 Chuck McManis <cmcmanis@mcmanis.com>\n * Copyright (C) 2016 Maxime Vincent <maxime.vince@gmail.com>\n *\n * This library is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this library.  If not, see <http://www.gnu.org/licenses/>.\n */\n/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: \n *          Maxime Vincent <maxime.vince@gmail.com>\n *          Chuck McManis <cmcmanis@mcmanis.com>\n *          Daniele Lacamera <root@danielinux.net>\n * \n *\n */\n\n#include <stdint.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/fsmc.h>\n#include \"frosted.h\"\n\n#define SDRAM_BASE_ADDRESS ((uint8_t *)(0xC0000000))\n\n/*\n * This is just syntactic sugar but it helps, all of these\n * GPIO pins get configured in exactly the same way.\n */\nstatic const struct {\n\tuint32_t\tgpio;\n\tuint16_t\tpins;\n} sdram_pins[6] = {\n\t{GPIOC, GPIO3 },\n\t{GPIOD, GPIO0 | GPIO1 | GPIO3 | GPIO8 | GPIO9 | GPIO10 | GPIO14 | GPIO15},\n\t{GPIOE, GPIO0 | GPIO1 | GPIO7 | GPIO8 | GPIO9 | GPIO10 |\n\t\t\tGPIO11 | GPIO12 | GPIO13 | GPIO14 | GPIO15 },\n\t{GPIOF, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | GPIO5 | GPIO11 |\n\t\t\tGPIO12 | GPIO13 | GPIO14 | GPIO15 },\n\t{GPIOG, GPIO0 | GPIO1 | GPIO4 | GPIO5 | GPIO8 | GPIO15},\n\t{GPIOH, GPIO3 | GPIO5 }\n};\n\nstatic struct sdram_timing timing = {\n    .trcd = 2,      /* RCD Delay */\n    .trp = 2,       /* RP Delay */\n    .twr = 2,       /* Write Recovery Time */\n    .trc = 7,       /* Row Cycle Delay */\n    .tras = 4,      /* Self Refresh Time */\n    .txsr = 7,      /* Exit Self Refresh Time */\n    .tmrd = 2,      /* Load to Active Delay */\n};\n\n/*\n * Initialize the SD RAM controller.\n */\nvoid sdram_init(void)\n{\n    int i, now;\n    uint32_t cr_tmp, tr_tmp; /* control, timing registers */\n\n\t/*\n\t* First all the GPIO pins that end up as SDRAM pins\n\t*/\n\trcc_periph_clock_enable(RCC_GPIOC);\n\trcc_periph_clock_enable(RCC_GPIOD);\n\trcc_periph_clock_enable(RCC_GPIOE);\n\trcc_periph_clock_enable(RCC_GPIOF);\n\trcc_periph_clock_enable(RCC_GPIOG);\n\trcc_periph_clock_enable(RCC_GPIOH);\n\n\tfor (i = 0; i < 6; i++) {\n\t\tgpio_mode_setup(sdram_pins[i].gpio,\n\t\t\t\tGPIO_MODE_AF, GPIO_PUPD_NONE,\n\t\t\t\tsdram_pins[i].pins);\n\t\tgpio_set_output_options(sdram_pins[i].gpio, GPIO_OTYPE_PP,\n\t\t\t\t\tGPIO_OSPEED_100MHZ, sdram_pins[i].pins);\n\t\tgpio_set_af(sdram_pins[i].gpio, GPIO_AF12, sdram_pins[i].pins);\n\t}\n\n    /* Enable the SDRAM Controller */\n#if 1\n    rcc_periph_clock_enable(RCC_FMC);\n#else\n    rcc_peripheral_enable_clock(&RCC_AHB3ENR, RCC_AHB3ENR_FMCEN);\n#endif\n\n    /* Note the STM32F746G-DISCO board has the ram attached to bank 1 */\n    /* Timing parameters computed for a ~200 MHz  clock */\n    /* These parameters are specific to the SDRAM chip on the board */\n\n    cr_tmp  = FMC_SDCR_RPIPE_NONE;\n    cr_tmp |= FMC_SDCR_SDCLK_2HCLK;\n    cr_tmp |= FMC_SDCR_CAS_2CYC;\n    cr_tmp |= FMC_SDCR_NB4;\n    cr_tmp |= FMC_SDCR_MWID_16b;\n    cr_tmp |= FMC_SDCR_NR_12;\n    cr_tmp |= FMC_SDCR_NC_8;\n\n\t/* We're programming BANK 1\n     * Per the manual some of the parameters only work in CR1 and TR1\n     * So when using BANK2: we need pull those off and put them in the right place.\n     * FMC_SDCR1 |= (cr_tmp); // & FMC_SDCR_DNC_MASK);\n     * FMC_SDCR2 = cr_tmp;\n     */\n\tFMC_SDCR1 = (cr_tmp);\n\n    tr_tmp = sdram_timing(&timing);\n\tFMC_SDTR1 = (tr_tmp);\n\n    /* Now start up the Controller per the manual\n     *  - Clock config enable\n     *  - PALL state\n     *  - set auto refresh\n     *  - Load the Mode Register\n     */\n    sdram_command(SDRAM_BANK1, SDRAM_CLK_CONF, 1, 0);\n\n    /* sleep at least 100uS */\n    now = jiffies;\n    //while (now + 2 > jiffies) {};\n\n    sdram_command(SDRAM_BANK1, SDRAM_PALL, 1, 0);\n    sdram_command(SDRAM_BANK1, SDRAM_AUTO_REFRESH, 8, 0);\n    tr_tmp = SDRAM_MODE_BURST_LENGTH_1              |\n                SDRAM_MODE_BURST_TYPE_SEQUENTIAL    |\n                SDRAM_MODE_CAS_LATENCY_2        |\n                SDRAM_MODE_OPERATING_MODE_STANDARD  |\n                SDRAM_MODE_WRITEBURST_MODE_SINGLE;\n    sdram_command(SDRAM_BANK1, SDRAM_LOAD_MODE, 1, tr_tmp);\n\n    /*\n     * set the refresh counter to insure we kick off an\n     * auto refresh often enough to prevent data loss.\n     */\n    FMC_SDRTR = ((uint32_t)0x0603);   /* SDRAM refresh counter (100Mhz SD clock) */\n    /* and Poof! a 8 megabytes of ram shows up in the address space */\n\n    /* Disable write protection */\n    FMC_SDCR1 &= ~FMC_SDCR_WP_ENABLE;\n}\n\n"
  },
  {
    "path": "kernel/drivers/stmpe811.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: brabo\n *\n */\n\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"ioctl.h\"\n#include \"stmpe811.h\"\n#include \"gpio.h\"\n#include \"exti.h\"\n#include \"dma.h\"\n#include \"i2c.h\"\n\n#define STMPE811_I2C_ADDR       0x82\n#define STMPE811_CHIP_ID        0x00    /* STMPE811 Device identification */\n\n/* Registers */\n#define STMPE811_CHIP_ID        0x00    /* STMPE811 Device identification */\n#define STMPE811_ID_VER         0x02    /* STMPE811 Revision number */\n#define STMPE811_SYS_CTRL1      0x03    /* Reset control */\n#define STMPE811_SYS_CTRL2      0x04    /* Clock control */\n#define STMPE811_SPI_CFG        0x08    /* SPI interface configuration */\n#define STMPE811_INT_CTRL       0x09    /* Interrupt control register */\n#define STMPE811_INT_EN         0x0A    /* Interrupt enable register */\n#define STMPE811_INT_STA        0x0B    /* Interrupt status register */\n#define STMPE811_GPIO_EN        0x0C    /* GPIO interrupt enable register */\n#define STMPE811_GPIO_INT_STA   0x0D    /* GPIO interrupt status register */\n#define STMPE811_ADC_INT_EN     0x0E    /* ADC interrupt enable register */\n#define STMPE811_ADC_INT_STA    0x0F    /* ADC interface status register */\n#define STMPE811_GPIO_SET_PIN   0x10    /* GPIO set pin register */\n#define STMPE811_GPIO_CLR_PIN   0x11    /* GPIO clear pin register */\n#define STMPE811_MP_STA         0x12    /* GPIO monitor pin state register */\n#define STMPE811_GPIO_DIR       0x13    /* GPIO direction register */\n#define STMPE811_GPIO_ED        0x14    /* GPIO edge detect register */\n#define STMPE811_GPIO_RE        0x15    /* GPIO rising edge register */\n#define STMPE811_GPIO_FE        0x16    /* GPIO falling edge register */\n#define STMPE811_GPIO_AF        0x17    /* Alternate function register */\n#define STMPE811_ADC_CTRL1      0x20    /* ADC control */\n#define STMPE811_ADC_CTRL2      0x21    /* ADC control */\n#define STMPE811_ADC_CAPT       0x22    /* To initiate ADC data acquisition */\n#define STMPE811_ADC_DATA_CHO   0x30    /* ADC channel 0 */\n#define STMPE811_ADC_DATA_CH1   0x32    /* ADC channel 1 */\n#define STMPE811_ADC_DATA_CH2   0x34    /* ADC channel 2 */\n#define STMPE811_ADC_DATA_CH3   0x36    /* ADC channel 3 */\n#define STMPE811_ADC_DATA_CH4   0x38    /* ADC channel 4 */\n#define STMPE811_ADC_DATA_CH5   0x3A    /* ADC channel 5 */\n#define STMPE811_ADC_DATA_CH6   0x3C    /* ADC channel 6 */\n#define STMPE811_ADC_DATA_CH7   0x3E    /* ADC channel 7 */\n#define STMPE811_TSC_CTRL       0x40    /* 4-wire tsc setup */\n#define STMPE811_TSC_CFG        0x41    /* Tsc configuration */\n#define STMPE811_WDW_TR_X       0x42    /* Window setup for top right X */\n#define STMPE811_WDW_TR_Y       0x44    /* Window setup for top right Y */\n#define STMPE811_WDW_BL_X       0x46    /* Window setup for bottom left X */\n#define STMPE811_WDW_BL_Y       0x48    /* Window setup for bottom left Y */\n#define STMPE811_FIFO_TH        0x4A    /* FIFO level to generate interrupt */\n#define STMPE811_FIFO_STA       0x4B    /* Current status of FIFO */\n#define STMPE811_FIFO_SIZE      0x4C    /* Current filled level of FIFO */\n#define STMPE811_TSC_DATA_X     0x4D    /* Data port for tsc data access */\n#define STMPE811_TSC_DATA_Y     0x4F    /* Data port for tsc data access */\n#define STMPE811_TSC_DATA_Z     0x51    /* Data port for tsc data access */\n#define STMPE811_TSC_DATA_XYZ   0x52    /* Data port for tsc data access */\n#define STMPE811_TSC_FRACTION_Z 0x56    /* Touchscreen controller FRACTION_Z */\n#define STMPE811_TSC_DATA       0x57    /* Data port for tsc data access */\n#define STMPE811_TSC_I_DRIVE    0x58    /* Touchscreen controller drivel */\n#define STMPE811_TSC_SHIELD     0x59    /* Touchscreen controller shield */\n#define STMPE811_TEMP_CTRL      0x60    /* Temperature sensor setup */\n#define STMPE811_TEMP_DATA      0x61    /* Temperature data access port */\n#define STMPE811_TEMP_TH        0x62    /* Threshold for temp controlled int */\n\n#define STMPE811_SYS_CTRL2_ADC_OFF      (1 << 0)\n#define STMPE811_SYS_CTRL2_TSC_OFF      (1 << 1)\n#define STMPE811_SYS_CTRL2_GPIO_OFF     (1 << 2)\n#define STMPE811_SYS_CTRL2_TS_OFF       (1 << 3)\n\n#define STMPE811_TEMP_CTRL_EN           (1 << 0)\n#define STMPE811_TEMP_CTRL_ACQ          (1 << 1)\n#define STMPE811_TEMP_DATA_MSB_MASK     0x03\n\n#define STMPE811_TSC_CTRL_EN            (1 << 0)\n\n#define STMPE811_INT_EN_TOUCH_DET       (1 << 0)\n#define STMPE811_INT_EN_FIFO_TH         (1 << 1)\n#define STMPE811_INT_EN_FIFO_OFLOW      (1 << 2)\n#define STMPE811_INT_EN_FIFO_FULL       (1 << 3)\n#define STMPE811_INT_EN_FIFO_EMPTY      (1 << 4)\n#define STMPE811_INT_EN_TEMP_SENS       (1 << 5)\n#define STMPE811_INT_EN_ADC             (1 << 6)\n#define STMPE811_INT_EN_GPIO            (1 << 7)\n\n#define STMPE811_SYS_CTRL1_SOFT_RESET   (1 << 1)\n\n#define STMPE811_FIFO_STA_TOUCH_DET     (1 << 0)\n\n#define STMPE811_INT_CTRL_GLOBAL_INT    (1 << 0)\n\nenum stmpe811_state {\n    STMPE811_STATE_IDLE = 0,\n    STMPE811_STATE_BUSY,\n    STMPE811_STATE_TX_RDY,\n    STMPE811_STATE_RX_RDY,\n    STMPE811_STATE_RDY,\n    STMPE811_STATE_RD,\n    STMPE811_STATE_INIT,\n};\n\nenum insta {\n    STMPE811_INIT_1,\n    STMPE811_INIT_2,\n    STMPE811_INIT_3,\n    STMPE811_INIT_4,\n    STMPE811_INIT_5,\n    STMPE811_INIT_6,\n    STMPE811_INIT_7,\n    STMPE811_INIT_8,\n    STMPE811_INIT_9,\n    STMPE811_INIT_10,\n    STMPE811_INIT_11,\n    STMPE811_INIT_12,\n    STMPE811_INIT_13,\n    STMPE811_INIT_14,\n    STMPE811_INIT_15,\n    STMPE811_INIT_16,\n    STMPE811_INIT_17,\n    STMPE811_INIT_18,\n    STMPE811_INIT_19,\n    STMPE811_INIT_20,\n    STMPE811_INIT_21,\n    STMPE811_INIT_22,\n    STMPE811_INIT_23,\n    STMPE811_INIT_24,\n    STMPE811_INIT_25,\n    STMPE811_INIT_26,\n    STMPE811_INIT_27,\n    STMPE811_INIT_28,\n    STMPE811_INIT_29,\n    STMPE811_INIT_30,\n    STMPE811_INIT_31,\n    STMPE811_INIT_32,\n    STMPE811_INIT_33,\n    STMPE811_INIT_34,\n    STMPE811_INIT_35,\n    STMPE811_INIT_36,\n    STMPE811_INIT_37,\n    STMPE811_INIT_38,\n    STMPE811_INIT_39,\n    STMPE811_INIT_40,\n    STMPE811_INIT_41,\n    STMPE811_INIT_42,\n    STMPE811_INIT_43,\n    STMPE811_INIT_44,\n    STMPE811_INIT_45,\n    STMPE811_INIT_46,\n    STMPE811_INIT_47,\n    STMPE811_INIT_48,\n    STMPE811_INIT_49,\n    STMPE811_INIT_50,\n    STMPE811_INIT_51,\n    STMPE811_INIT_52,\n    STMPE811_INIT_53,\n    STMPE811_INIT_54,\n    STMPE811_INIT_55,\n    STMPE811_INIT_56,\n    STMPE811_INIT_57,\n};\n\nstruct dev_stmpe811 {\n    struct i2c_slave i2c; /* As first argument, so isr callbacks will use this as arg */\n    struct device *dev;\n    unsigned int flags;\n    int eidx;\n    enum stmpe811_state state;\n    volatile uint16_t cnt;\n} TS;\n\nstatic int devstmpe811_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int devstmpe811_close(struct fnode *fno);\nstatic int stmpe811_fno_init(struct dev_stmpe811 *s);\n\nstatic struct module mod_devstmpe811 = {\n    .family = FAMILY_FILE,\n    .name = \"stmpe811\",\n    .ops.open = device_open,\n    .ops.read = devstmpe811_read,\n    .ops.close = devstmpe811_close,\n};\n\nstatic uint8_t buffer;\n\nstatic void *sys_ctrl1_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_SYS_CTRL1, &buffer, 1);\n}\n\nstatic void *set_softreset(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= STMPE811_SYS_CTRL1_SOFT_RESET;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_SYS_CTRL1, &buffer, 1);\n}\n\nstatic void *unset_softreset(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer &= ~STMPE811_SYS_CTRL1_SOFT_RESET;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_SYS_CTRL1, &buffer, 1);\n}\n\nstatic void *sys_ctrl2_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_SYS_CTRL2, &buffer, 1);\n}\n\nstatic void *ts_off(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = STMPE811_SYS_CTRL2_TS_OFF;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_SYS_CTRL2, &buffer, 1);\n}\n\nstatic void *gpio_off(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= STMPE811_SYS_CTRL2_GPIO_OFF;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_SYS_CTRL2, &buffer, 1);\n}\n\nstatic void *int_en_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_INT_EN, &buffer, 1);\n}\n\nstatic void *enable_fifo_oflow(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = STMPE811_INT_EN_FIFO_OFLOW;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_INT_EN, &buffer, 1);\n}\n\nstatic void *enable_fifo_th(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= STMPE811_INT_EN_FIFO_TH;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_INT_EN, &buffer, 1);\n}\n\nstatic void *enable_fifo_touch_det(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= STMPE811_INT_EN_TOUCH_DET;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_INT_EN, &buffer, 1);\n}\n\nstatic void *adc_ctrl1_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_ADC_CTRL1, &buffer, 1);\n}\n\nstatic void *set_adc_sample(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    /* set to 80 cycles */\n    buffer |= 0x40;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_ADC_CTRL1, &buffer, 1);\n}\n\nstatic void *set_adc_res(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    /* set adc resolution to 12(?) bit */\n    buffer |= 0x08;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_ADC_CTRL1, &buffer, 1);\n}\n\nstatic void *adc_ctrl2_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_ADC_CTRL2, &buffer, 1);\n}\n\nstatic void *set_adc_freq(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    /* set adc clock speed to 3.25 MHz */\n    buffer |= 0x01;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_ADC_CTRL2, &buffer, 1);\n}\n\nstatic void *gpio_af_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_GPIO_AF, &buffer, 1);\n}\n\nstatic void *set_gpio_af(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_GPIO_AF, &buffer, 1);\n}\n\nstatic void *tsc_cfg_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_TSC_CFG, &buffer, 1);\n}\n\nstatic void *set_tsc(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x9A;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_TSC_CFG, &buffer, 1);\n}\n\nstatic void *fifo_th_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_FIFO_TH, &buffer, 1);\n}\n\nstatic void *set_fifo_th(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x01;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_FIFO_TH, &buffer, 1);\n}\n\nstatic void *fifo_sta_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_FIFO_STA, &buffer, 1);\n}\n\nstatic void *set_fifo_sta_touchdet(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= STMPE811_FIFO_STA_TOUCH_DET;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_FIFO_STA, &buffer, 1);\n}\n\nstatic void *unset_fifo_sta_touchdet(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer &= ~STMPE811_FIFO_STA_TOUCH_DET;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_FIFO_STA, &buffer, 1);\n}\n\nstatic void *tsc_fracz_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_TSC_FRACTION_Z, &buffer, 1);\n}\n\nstatic void *set_tsc_fracz(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= 0x07;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_TSC_FRACTION_Z, &buffer, 1);\n}\n\nstatic void *tsc_idrive_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_TSC_I_DRIVE, &buffer, 1);\n}\n\nstatic void *set_tsc_idrive(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= 0x01;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_TSC_I_DRIVE, &buffer, 1);\n}\n\nstatic void *tsc_on(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer &= ~STMPE811_SYS_CTRL2_TSC_OFF;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_SYS_CTRL2, &buffer, 1);\n}\n\nstatic void *tsc_ctrl_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_TSC_CTRL, &buffer, 1);\n}\n\nstatic void *enable_tsc(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= STMPE811_TSC_CTRL_EN;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_TSC_CTRL, &buffer, 1);\n}\n\nstatic void *int_sta_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_INT_STA, &buffer, 1);\n}\n\nstatic void *set_int_sta_tsc_en(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0xFF;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_INT_STA, &buffer, 1);\n}\n\nstatic void *int_ctrl_r(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer = 0x00;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_INT_CTRL, &buffer, 1);\n}\n\nstatic void *set_int_ctrl_global_en(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer |= STMPE811_INT_CTRL_GLOBAL_INT;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_INT_CTRL, &buffer, 1);\n}\n\nstatic void *gpio_on(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    buffer &= ~STMPE811_SYS_CTRL2_GPIO_OFF;\n\n    i2c_init_write(&stmpe811->i2c, STMPE811_SYS_CTRL2, &buffer, 1);\n}\n\nstatic void *init_end(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_SYS_CTRL2, &buffer, 1);\n    stmpe811_fno_init(stmpe811);\n    register_module(&mod_devstmpe811);\n    stmpe811->cnt = 0;\n    stmpe811->state = STMPE811_STATE_IDLE;\n}\n\nstruct ts_init {\n    enum insta state;\n    int (*init)(struct dev_stmpe811 *stmpe811);\n};\n\nstatic const struct ts_init ts_init[] = {\n    { STMPE811_INIT_1, sys_ctrl1_r },\n    { STMPE811_INIT_2, set_softreset },\n    { STMPE811_INIT_3, unset_softreset },\n    { STMPE811_INIT_4, sys_ctrl2_r },\n    { STMPE811_INIT_5, ts_off },\n    { STMPE811_INIT_6, gpio_off },\n    { STMPE811_INIT_7, sys_ctrl2_r },\n    { STMPE811_INIT_8, int_en_r },\n    { STMPE811_INIT_9, enable_fifo_oflow },\n    { STMPE811_INIT_10, enable_fifo_th },\n    { STMPE811_INIT_11, enable_fifo_touch_det },\n    { STMPE811_INIT_12, int_en_r },\n    { STMPE811_INIT_13, adc_ctrl1_r },\n    { STMPE811_INIT_14, set_adc_sample },\n    { STMPE811_INIT_15, set_adc_res },\n    { STMPE811_INIT_16, adc_ctrl1_r },\n    { STMPE811_INIT_17, adc_ctrl2_r },\n    { STMPE811_INIT_18, set_adc_freq },\n    { STMPE811_INIT_19, adc_ctrl2_r },\n    { STMPE811_INIT_20, gpio_af_r },\n    { STMPE811_INIT_21, set_gpio_af },\n    { STMPE811_INIT_22, gpio_af_r },\n    { STMPE811_INIT_23, tsc_cfg_r },\n    { STMPE811_INIT_24, set_tsc },\n    { STMPE811_INIT_25, tsc_cfg_r },\n    { STMPE811_INIT_26, fifo_th_r },\n    { STMPE811_INIT_27, set_fifo_th },\n    { STMPE811_INIT_28, fifo_th_r },\n    { STMPE811_INIT_29, fifo_sta_r },\n    { STMPE811_INIT_30, set_fifo_sta_touchdet },\n    { STMPE811_INIT_31, unset_fifo_sta_touchdet },\n    { STMPE811_INIT_32, fifo_sta_r },\n    { STMPE811_INIT_33, tsc_fracz_r },\n    { STMPE811_INIT_34, set_tsc_fracz },\n    { STMPE811_INIT_35, tsc_fracz_r },\n    { STMPE811_INIT_36, tsc_idrive_r },\n    { STMPE811_INIT_37, set_tsc_idrive },\n    { STMPE811_INIT_38, tsc_idrive_r },\n    { STMPE811_INIT_39, sys_ctrl2_r },\n    { STMPE811_INIT_40, tsc_on },\n    { STMPE811_INIT_41, sys_ctrl2_r },\n    { STMPE811_INIT_42, tsc_ctrl_r },\n    { STMPE811_INIT_43, enable_tsc },\n    { STMPE811_INIT_44, tsc_ctrl_r },\n    { STMPE811_INIT_45, int_sta_r },\n    { STMPE811_INIT_46, set_int_sta_tsc_en },\n    { STMPE811_INIT_47, int_sta_r },\n    { STMPE811_INIT_48, int_ctrl_r },\n    { STMPE811_INIT_49, set_int_ctrl_global_en },\n    { STMPE811_INIT_50, int_ctrl_r },\n    { STMPE811_INIT_51, sys_ctrl2_r },\n    { STMPE811_INIT_52, gpio_on },\n    { STMPE811_INIT_53, sys_ctrl2_r },\n    { STMPE811_INIT_54, init_end },\n};\n\nstatic uint32_t xy;\n\nstatic void *ts_read_touch(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_TSC_CTRL, &buffer, 1);\n}\n\n\nstatic void *ts_read_x_0(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    if ((buffer & 0x80) == 0) {\n        /* no touch, return 0xFFFFFFFF throuhg xy */\n        xy = 0xFFFFFFFF;\n\n        exti_enable(stmpe811->eidx, 0);\n        stmpe811->state = STMPE811_STATE_RDY;\n        stmpe811->cnt = 0;\n\n        if (stmpe811->dev->task) {\n            task_resume(stmpe811->dev->task);\n        }\n    } else {\n        i2c_init_read(&stmpe811->i2c, STMPE811_TSC_DATA_X, &buffer, 1);\n    }\n}\n\nstatic void *ts_read_x_1(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    xy = buffer;\n\n    i2c_init_read(&stmpe811->i2c, (STMPE811_TSC_DATA_X + 1), &buffer, 1);\n}\n\nstatic void *ts_read_y_0(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    xy |= (buffer << 8);\n\n    i2c_init_read(&stmpe811->i2c, STMPE811_TSC_DATA_Y, &buffer, 1);\n}\n\nstatic void *ts_read_y_1(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    xy |= (buffer << 16);\n\n    i2c_init_read(&stmpe811->i2c, (STMPE811_TSC_DATA_Y + 1), &buffer, 1);\n}\n\nstatic void *ts_read_end(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    xy |= (buffer << 24);\n\n    exti_enable(stmpe811->eidx, 0);\n    stmpe811->state = STMPE811_STATE_RDY;\n\n    if (stmpe811->dev->task> 0) {\n        task_resume(stmpe811->dev->task);\n    }\n}\n\nenum ts_read_state {\n    TS_READ_TOUCH,\n    TS_READ_X_0,\n    TS_READ_X_1,\n    TS_READ_Y_0,\n    TS_READ_Y_1,\n};\n\nstruct ts_read {\n    enum ts_read_state state;\n    int (*call)(struct dev_stmpe811 *stmpe811);\n};\n\nstatic const struct ts_read ts_read[] = {\n    { TS_READ_X_0, ts_read_x_0 },\n    { TS_READ_X_0, ts_read_x_0 },\n    { TS_READ_X_1, ts_read_x_1 },\n    { TS_READ_Y_0, ts_read_y_0 },\n    { TS_READ_Y_1, ts_read_y_1 },\n};\n/* I2C operation callbacks, executed in IRQ context, and with I2C mutex held. */\nstatic void stmpe811_tx_isr(struct i2c_slave *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    if (stmpe811->state == STMPE811_STATE_INIT) {\n        void (*next_f)(void *) = ts_init[stmpe811->cnt++].init;\n        tasklet_add(next_f, stmpe811);\n    }\n}\n\nstatic void stmpe811_rx_isr(struct i2c_slave *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n\n    if (stmpe811->state == STMPE811_STATE_INIT) {\n        void (*next_f)(void *) = ts_init[stmpe811->cnt++].init;\n        tasklet_add(next_f, stmpe811);\n    }\n\n    if (stmpe811->state == STMPE811_STATE_RD) {\n        void (*next_f)(void *) = ts_read[stmpe811->cnt++].call;\n        tasklet_add(next_f, stmpe811);\n    }\n}\n\nstatic void ts_isr(void *arg)\n{\n    struct dev_stmpe811 *stmpe811 = (struct dev_stmpe811 *)arg;\n    stmpe811->state = STMPE811_STATE_BUSY;\n    i2c_init_read(&stmpe811->i2c, STMPE811_TSC_DATA_X, &buffer, 1);\n}\n\nstatic int devstmpe811_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct dev_stmpe811 *stmpe811;\n\n    if (len == 0)\n        return len;\n\n    if (len != 4)\n        return -EINVAL;\n\n    stmpe811 = (struct dev_stmpe811 *)FNO_MOD_PRIV(fno, &mod_devstmpe811);\n\n    if (!stmpe811)\n        return EINVAL;\n\n    if (stmpe811->state == STMPE811_STATE_IDLE) {\n        if ((stmpe811->dev->task) && (stmpe811->dev->task != this_task())) {\n            return -EBUSY;\n        }\n        stmpe811->dev->task = this_task();\n\n        task_suspend();\n        exti_enable(stmpe811->eidx, 1);\n        return SYS_CALL_AGAIN;\n    } else if (stmpe811->state == STMPE811_STATE_RDY) {\n        memcpy(buf, &xy, 4);\n        stmpe811->dev->task = 0;\n        stmpe811->state = STMPE811_STATE_IDLE;\n        return sizeof(uint32_t);\n    }\n}\n\nstatic int devstmpe811_close(struct fnode *fno)\n{\n    return 0;\n}\n\n\nstatic int stmpe811_fno_init(struct dev_stmpe811 *s)\n{\n    static int num_ts = 0;\n    char name[4] = \"ts\";\n    struct fnode *devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return -ENOENT;\n\n\n    name[2] =  '0' + num_ts++;\n    s->dev = device_fno_init(&mod_devstmpe811, name, devfs, FL_RDONLY, s);\n    s->dev->task = NULL;\n    return 0;\n\n}\n\nint stmpe811_init(struct ts_config *ts)\n{\n    struct dev_stmpe811 *stmpe811;\n    stmpe811 = &TS;\n    memset(stmpe811, 0, sizeof(struct dev_stmpe811));\n\n    gpio_create(&mod_devstmpe811, &ts->gpio);\n\n    stmpe811->eidx = exti_register(ts->gpio.base, ts->gpio.pin, GPIO_TRIGGER_RAISE, ts_isr, &ts->gpio);\n\n    /* Populate i2c_slave struct */\n    stmpe811->i2c.bus = ts->bus;\n    stmpe811->i2c.address = STMPE811_I2C_ADDR;\n    stmpe811->i2c.isr_tx = stmpe811_tx_isr;\n    stmpe811->i2c.isr_rx = stmpe811_rx_isr;\n    stmpe811->state = STMPE811_STATE_INIT;\n    stmpe811->cnt = 0;\n\n    i2c_init_read(&stmpe811->i2c, (STMPE811_CHIP_ID + 1), &buffer, 1);\n\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/stmpe811.h",
    "content": "#ifndef INC_STMPE811\n#define INC_STMPE811\n\n#include \"gpio.h\"\n\nstruct ts_config {\n    struct gpio_config gpio;\n    uint8_t bus;\n};\n\n\nint stmpe811_init(struct ts_config *ts);\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/tty_console.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"framebuffer.h\"\n\n#define KBD_PATH \"/dev/kbd0\"\n#define FBCON_PATH \"/dev/fbcon\"\n\n#define KBD_MOD \"usbkbd\"\n#define FBCON_MOD \"fbcon\"\n\n\nstatic struct tty_console {\n    struct device *dev;\n    struct fnode *kbd;\n    struct fnode *fbcon;\n    struct module *mod_kbd;\n    struct module *mod_fbcon;\n    uint16_t pid;\n} TTY;\n\nstatic int tty_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int tty_poll(struct fnode *fno, uint16_t events, uint16_t *revents);\nstatic int tty_write(struct fnode *fno, const void *buf, unsigned int len);\nstatic int tty_seek(struct fnode *fno, int off, int whence);\nstatic void tty_attach(struct fnode *fno, int pid);\n\nstatic struct module mod_ttycon = {\n    .family = FAMILY_DEV,\n    .name = \"tty\",\n    .ops.open = device_open,\n    .ops.read = tty_read,\n    .ops.poll = tty_poll,\n    .ops.write = tty_write,\n    .ops.seek = tty_seek,\n    .ops.tty_attach = tty_attach\n};\n\nstatic void devfile_create(void) \n{\n    char name[5] = \"tty\";\n    struct fnode *devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return;\n    TTY.dev = device_fno_init(&mod_ttycon, name, devfs, FL_TTY, &TTY);\n}\n\nint tty_console_init(void)\n{\n    TTY.mod_kbd = module_search(KBD_MOD);\n    TTY.mod_fbcon = module_search(FBCON_MOD);\n    if(!TTY.mod_kbd || !TTY.mod_fbcon)\n        return -1;\n    TTY.kbd = fno_search(KBD_PATH);\n    TTY.fbcon = fno_search(FBCON_PATH);\n    devfile_create();\n    return 0;\n}\n\nstatic void tty_send_break(void *arg)\n{\n    int *pid = (int *)(arg);\n    if (pid)\n        task_kill(*pid, 2);\n}\n\nstatic int tty_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    int ret, i;\n    if (!TTY.kbd)\n        TTY.kbd = fno_search(KBD_PATH);\n    if (!TTY.kbd)\n        return 0;\n    ret = TTY.mod_kbd->ops.read(TTY.kbd, buf, len);\n    if (TTY.pid > 1) {\n        for (i = 0; i < ret; i++) {\n            if (((uint8_t *)buf)[i] == 0x03) /* Ctrl + c*/\n                tasklet_add(tty_send_break, &TTY.pid); \n        }\n    }\n    return ret;\n}\n\nstatic int tty_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    if (!TTY.kbd)\n        TTY.kbd = fno_search(KBD_PATH);\n    if (!TTY.kbd)\n        return 0;\n    return TTY.mod_kbd->ops.poll(TTY.kbd, events, revents);\n}\n\nstatic int tty_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    if (!TTY.fbcon)\n        TTY.fbcon = fno_search(FBCON_PATH);\n    return TTY.mod_fbcon->ops.write(TTY.fbcon, buf, len);\n}\n\nstatic int tty_seek(struct fnode *fno, int off, int whence)\n{\n    if (!TTY.fbcon)\n        TTY.fbcon = fno_search(FBCON_PATH);\n    if (!TTY.fbcon)\n        return -ENOENT;\n    return TTY.mod_fbcon->ops.seek(TTY.fbcon, off, whence);\n}\n\nstatic void tty_attach(struct fnode *fno, int pid)\n{\n    if (!TTY.fbcon)\n        TTY.fbcon = fno_search(FBCON_PATH);\n    if (!TTY.fbcon)\n        return;\n    TTY.mod_fbcon->ops.tty_attach(TTY.fbcon, pid);\n    TTY.pid = pid;\n}\n\n"
  },
  {
    "path": "kernel/drivers/tty_console.h",
    "content": "\n#ifndef INC_TTY_CONSOLE\n#define INC_TTY_CONSOLE\n#include \"frosted.h\"\n#ifdef CONFIG_DEVTTY_CONSOLE\nint tty_console_init(void);\n#else\n#define tty_console_init() (-ENOENT)\n#endif\n\n\n#endif\n\n"
  },
  {
    "path": "kernel/drivers/uart.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n\n#include \"frosted.h\"\n#include \"device.h\"\n#include \"cirbuf.h\"\n#include <stdint.h>\n#include \"uart_dev.h\"\n#include \"uart.h\"\n#include \"poll.h\"\n\n#include \"unicore-mx/cm3/nvic.h\"\n\n#ifdef LM3S\n#   include \"unicore-mx/lm3s/usart.h\"\n#   define CLOCK_ENABLE(C)\n#   define USART_SR_RXNE  USART_IC_RX\n#   define USART_SR_TXE   USART_IC_TX\nstatic inline uint32_t get_interrupt_source(uint32_t base)\n{\n    return USART_RIS(base);\n}\n#endif\n#ifdef STM32F4\n#   include \"unicore-mx/stm32/usart.h\"\n#   include \"unicore-mx/stm32/rcc.h\"\n#   define CLOCK_ENABLE(C)                 rcc_periph_clock_enable(C);\n#   define usart_clear_rx_interrupt(x) do{}while(0)\n#   define usart_clear_tx_interrupt(x) do{}while(0)\nstatic inline uint32_t get_interrupt_source(uint32_t base)\n{\n    return USART_SR(base);\n}\n#endif\n#ifdef STM32F7\n#   include \"unicore-mx/stm32/usart.h\"\n#   include \"unicore-mx/stm32/rcc.h\"\n#   define CLOCK_ENABLE(C)                 rcc_periph_clock_enable(C);\nstatic inline uint32_t get_interrupt_source(uint32_t base)\n{\n\tuint32_t flag_set = USART_ISR(base);\n    uint32_t ret =0;\n    if (flag_set & USART_ISR_TXE)\n        ret |= USART_SR_TXE;\n    if ((flag_set != 0) && USART_ISR_RXNE)\n        ret |= USART_SR_RXNE;\n    return ret;\n}\n#endif\n#ifdef LPC17XX\n#   include \"unicore-mx/lpc17xx/uart.h\"\n#   include \"unicore-mx/lpc17xx/pwr.h\"\n#   define CLOCK_ENABLE(C) pwr_enable_peripherals(C)\nstatic inline uint32_t get_interrupt_source(uint32_t base)\n{\n    return UART_IIR(base);\n}\n#endif\n#if defined(NRF51) || defined(NRF52)\n#   include \"unicore-mx/nrf/uart.h\"\n#   define CLOCK_ENABLE(C)               do{} while(0)\n#   define usart_enable                  uart_enable\n#   define usart_set_baudrate            uart_set_baudrate\n#   define usart_set_databits(x, y)      do {} while(0)\n#   define usart_set_stopbits(x, y)      do {} while(0)\n#   define usart_set_parity              uart_set_parity\n#   define usart_set_flow_control        uart_set_flow_control\n#   define usart_set_mode(x, y)          do {} while(0)\n#   define usart_enable_rx_interrupt(x)  do { \\\n                                              uart_enable_interrupts(x, UART_INTEN_RXDRDY); \\\n                                              uart_start_rx(x); \\\n                                         } while(0)\n#   define usart_disable_rx_interrupt(x) do { \\\n                                              uart_disable_interrupts(x, UART_INTEN_RXDRDY); \\\n                                              uart_stop_rx(x); \\\n                                         } while(0)\n#   define usart_enable_tx_interrupt(x)  do { \\\n                                              uart_enable_interrupts(x, UART_INTEN_TXDRDY); \\\n                                              uart_start_tx(x); \\\n                                         } while(0)\n#   define usart_disable_tx_interrupt(x) do { \\\n                                              uart_disable_interrupts(x, UART_INTEN_TXDRDY); \\\n                                              uart_stop_tx(x); \\\n                                         } while(0)\n#   define usart_clear_tx_interrupt(x)   uart_clear_events(UART_EVENT_TXDRDY(x))\n#   define usart_clear_rx_interrupt(x)   uart_clear_events(UART_EVENT_RXDRDY(x))\n#   define usart_is_send_ready(x)        UART_EVENT_CTS(x)\n#   define usart_is_recv_ready(x)        1\n#   define usart_send                    uart_send\n#   define usart_recv                    uart_recv\n#   define USART_SR_RXNE                 1\n#   define USART_SR_TXE                  2\n\nstatic inline uint32_t get_interrupt_source(uint32_t base)\n{\n    if(UART_EVENT_TXDRDY(base))\n        return USART_SR_TXE;\n    if(UART_EVENT_RXDRDY(base))\n        return USART_SR_RXNE;\n}\n#endif\n\nstruct dev_uart {\n    struct device * dev;\n    uint32_t base;\n    struct cirbuf *inbuf;\n    struct cirbuf *outbuf;\n    uint16_t sid;\n    uint8_t *w_start;\n    uint8_t *w_end;\n};\n\n#define MAX_UARTS 8\nstatic struct dev_uart *DEV_UART[MAX_UARTS] = { };\n\nstatic int devuart_write(struct fnode *fno, const void *buf, unsigned int len);\nstatic int devuart_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int devuart_poll(struct fnode *fno, uint16_t events, uint16_t *revents);\nstatic void devuart_tty_attach(struct fnode *fno, int pid);\n\nstatic struct module mod_devuart = {\n    .family = FAMILY_FILE,\n    .name = \"uart\",\n    .ops.open = device_open,\n    .ops.read = devuart_read,\n    .ops.poll = devuart_poll,\n    .ops.write = devuart_write,\n    .ops.tty_attach = devuart_tty_attach,\n};\n\nstatic void uart_send_break(void *arg)\n{\n    int *pid = (int *)(arg);\n    if (pid)\n        task_kill(*pid, 2);\n}\n\nstatic void devuart_tty_attach(struct fnode *fno, int pid)\n{\n    struct dev_uart *uart = (struct dev_uart *)FNO_MOD_PRIV(fno, &mod_devuart);\n    if (uart->sid != pid) {\n        //kprintf(\"/dev/%s active job pid: %d\\r\\n\", fno->fname, pid);\n        uart->sid = pid;\n    }\n}\n\nvoid uart_isr(struct dev_uart *uart)\n{\n    uint32_t req;\n    if (!uart)\n        return;\n    req = get_interrupt_source(uart->base);\n    /* TX interrupt */\n    if (req & USART_SR_TXE) {\n        usart_clear_tx_interrupt(uart->base);\n\n//        if (this_task() != NULL) /* cannot spinlock in ISR! */\n//            mutex_lock(uart->dev->mutex);\n\n        /* Are there bytes left to be written? */\n        if (cirbuf_bytesinuse(uart->outbuf))\n        {\n            uint8_t outbyte;\n            cirbuf_readbyte(uart->outbuf, &outbyte);\n            usart_send(uart->base, (uint16_t)(outbyte));\n        } else {\n            usart_disable_tx_interrupt(uart->base);\n            /* If a process is attached, resume the process */\n            if (uart->dev->task != NULL)\n                task_resume(uart->dev->task);\n        }\n//        mutex_unlock(uart->dev->mutex);\n    }\n\n    /* RX interrupt */\n    if (req & USART_SR_RXNE) {\n        usart_clear_rx_interrupt(uart->base);\n        /* if data available */\n        if (usart_is_recv_ready(uart->base))\n        {\n            char byte = (char)(usart_recv(uart->base) & 0xFF);\n\n            /* Intercept ^C */\n            if (byte == 3) {\n                if (uart->sid > 1) {\n                    tasklet_add(uart_send_break, &uart->sid);\n                }\n                return;\n            }\n            /* read data into circular buffer */\n            cirbuf_writebyte(uart->inbuf, byte);\n        }\n        /* If a process is attached, resume the process */\n        if (uart->dev->task != NULL)\n            task_resume(uart->dev->task);\n    }\n}\n\nvoid uart0_isr(void)\n{\n    uart_isr(DEV_UART[0]);\n}\n\nvoid uart1_isr(void)\n{\n    uart_isr(DEV_UART[1]);\n}\n\nvoid uart2_isr(void)\n{\n    uart_isr(DEV_UART[2]);\n}\n\n#ifdef USART0\nvoid usart0_isr(void)\n{\n    uart_isr(DEV_UART[0]);\n}\n#endif\n\n#ifdef USART1\nvoid usart1_isr(void)\n{\n    uart_isr(DEV_UART[1]);\n}\n#endif\n#ifdef USART2\nvoid usart2_isr(void)\n{\n    uart_isr(DEV_UART[2]);\n}\n#endif\n#ifdef USART3\nvoid usart3_isr(void)\n{\n    uart_isr(DEV_UART[3]);\n}\n#endif\n#ifdef USART6\nvoid usart6_isr(void)\n{\n    uart_isr(DEV_UART[6]);\n}\n#endif\n\n\nstatic int devuart_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    int i;\n    char *ch = (char *)buf;\n    struct dev_uart *uart;\n\n    uart = (struct dev_uart *)FNO_MOD_PRIV(fno, &mod_devuart);\n    if (!uart)\n        return -1;\n\n    mutex_lock(uart->dev->mutex);\n    if (cirbuf_bytesinuse(uart->outbuf) && usart_is_send_ready(uart->base)) {\n        char c;\n        cirbuf_readbyte(uart->outbuf, &c);\n        usart_send(uart->base, (uint16_t) c);\n        usart_enable_tx_interrupt(uart->base);\n    }\n\n    if (!cirbuf_bytesfree(uart->outbuf)) {\n        mutex_unlock(uart->dev->mutex);\n        task_preempt();\n        return SYS_CALL_AGAIN;\n    }\n\n    if (len <= 0)\n        return len;\n    if (uart->w_start == NULL) {\n        uart->w_start = (uint8_t *)buf;\n        uart->w_end = ((uint8_t *)buf) + len;\n\n    } else {\n        /* previous transmit not finished, do not update w_start */\n    }\n\n\n    /* write to circular output buffer */\n    uart->w_start += cirbuf_writebytes(uart->outbuf, uart->w_start, uart->w_end - uart->w_start);\n    if (usart_is_send_ready(uart->base)) {\n        char c;\n        cirbuf_readbyte(uart->outbuf, &c);\n        usart_send(uart->base, (uint16_t) c);\n        usart_enable_tx_interrupt(uart->base);\n    }\n\n    if (cirbuf_bytesinuse(uart->outbuf) == 0) {\n        mutex_unlock(uart->dev->mutex);\n        usart_disable_tx_interrupt(uart->base);\n        uart->w_start = NULL;\n        uart->w_end = NULL;\n        return len;\n    }\n\n\n    if (uart->w_start < uart->w_end)\n    {\n        uart->dev->task = this_task();\n        mutex_unlock(uart->dev->mutex);\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n\n    mutex_unlock(uart->dev->mutex);\n    uart->w_start = NULL;\n    uart->w_end = NULL;\n    return len;\n}\n\n\nstatic int devuart_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    int out;\n    volatile int len_available;\n    char *ptr = (char *)buf;\n    struct dev_uart *uart;\n\n    if (len <= 0)\n        return len;\n\n    uart = (struct dev_uart *)FNO_MOD_PRIV(fno, &mod_devuart);\n    if (!uart)\n        return -1;\n\n    mutex_lock(uart->dev->mutex);\n    usart_disable_rx_interrupt(uart->base);\n    len_available =  cirbuf_bytesinuse(uart->inbuf);\n    if (len_available <= 0) {\n        uart->dev->task = this_task();\n        task_suspend();\n        mutex_unlock(uart->dev->mutex);\n        out = SYS_CALL_AGAIN;\n        goto again;\n    }\n\n    if (len_available < len)\n        len = len_available;\n\n    for(out = 0; out < len; out++) {\n        /* read data */\n        if (cirbuf_readbyte(uart->inbuf, ptr) != 0)\n            break;\n        ptr++;\n    }\n\nagain:\n    usart_enable_rx_interrupt(uart->base);\n    mutex_unlock(uart->dev->mutex);\n    return out;\n}\n\n\nstatic int devuart_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    int ret = 0;\n    struct dev_uart *uart;\n\n    uart = (struct dev_uart *)FNO_MOD_PRIV(fno, &mod_devuart);\n    if (!uart)\n        return -1;\n\n    uart->dev->task = this_task();\n    mutex_lock(uart->dev->mutex);\n    usart_disable_rx_interrupt(uart->base);\n    if ((events & POLLOUT) && (cirbuf_bytesfree(uart->outbuf) > 0)) {\n        *revents |= POLLOUT;\n        ret = 1;\n    }\n    if ((events == POLLIN) && (cirbuf_bytesinuse(uart->inbuf) > 0)) {\n        *revents |= POLLIN;\n        ret = 1;\n    }\n    usart_enable_rx_interrupt(uart->base);\n    mutex_unlock(uart->dev->mutex);\n    return ret;\n}\n\nstatic int uart_fno_init(const struct uart_config * addr)\n{\n    static int num_ttys = 0;\n    char name[6] = \"ttyS\";\n    struct fnode *devfs = fno_search(\"/dev\");\n    struct dev_uart *u;\n    if (!devfs)\n        return -ENOENT;\n\n    u = kalloc(sizeof(struct dev_uart));\n    if (!u)\n        return -ENOMEM;\n    memset(u, 0, sizeof(struct dev_uart));\n\n    name[4] =  '0' + num_ttys++;\n    u->base = addr->base;\n    u->dev = device_fno_init(&mod_devuart, name, devfs, FL_TTY, u);\n    u->inbuf = cirbuf_create(256);\n    u->outbuf = cirbuf_create(256);\n    u->dev->task = NULL;\n    DEV_UART[addr->devidx] = u;\n    return 0;\n\n}\n\nint uart_create(const struct uart_config *uart)\n{\n    if (uart->base == 0)\n        return -EINVAL;\n\n    gpio_create(&mod_devuart, &uart->pio_rx);\n    gpio_create(&mod_devuart, &uart->pio_tx);\n#if defined(NRF51) || defined(NRF52)\n    if(!uart->flow) {\n        uart_set_pins(uart->base, uart->pio_rx.pin, uart->pio_tx.pin,\n                                  UART_PSEL_OFF, UART_PSEL_OFF);\n    } else {\n        uart_set_pins(uart->base, uart->pio_rx.pin, uart->pio_tx.pin,\n                                  uart->pio_cts.pin, uart->pio_rts.pin);\n    }\n#endif\n\n    uart_fno_init(uart);\n    CLOCK_ENABLE(uart->rcc);\n    usart_enable_rx_interrupt(uart->base);\n    usart_set_baudrate(uart->base, uart->baudrate);\n    usart_set_databits(uart->base, uart->data_bits);\n    usart_set_stopbits(uart->base, uart->stop_bits);\n    usart_set_mode(uart->base, USART_MODE_TX_RX);\n    usart_set_parity(uart->base, uart->parity);\n    usart_set_flow_control(uart->base, uart->flow);\n#ifdef STM32F7\n    USART_CR1(uart->base) &= ~(USART_CR1_TCIE);\n#endif\n    usart_enable_rx_interrupt(uart->base);\n    nvic_enable_irq(uart->irq);\n    usart_enable(uart->base);\n}\n\nint uart_init(void)\n{\n    register_module(&mod_devuart);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/drivers/uart.h",
    "content": "#ifndef INC_UART\r\n#define INC_UART\r\n\r\n#include \"frosted.h\"\r\n#include \"gpio.h\"\r\n\r\n/* TX, RX, RTS, CTS, CK*/\r\n#define MAX_UART_PINS 5\r\n\r\nstruct uart_config {\r\n    uint8_t devidx;\r\n    uint32_t base;\r\n    uint32_t irq;\r\n    uint32_t rcc;\r\n    uint32_t baudrate;\r\n    uint8_t stop_bits;\r\n    uint8_t data_bits;\r\n    uint8_t parity;\r\n    uint8_t flow;\r\n    struct gpio_config pio_rx;\r\n    struct gpio_config pio_tx;\r\n    struct gpio_config pio_cts;\r\n    struct gpio_config pio_rts;\r\n};\r\n\r\n#ifdef CONFIG_DEVUART\r\nint uart_init(void);\r\nint uart_create(const struct uart_config *cfg);\r\n#else\r\n#define uart_init() (-ENOENT)\r\n#define uart_create(x) (-ENOENT)\r\n#endif\r\n\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "kernel/drivers/uart_dev.h",
    "content": "#ifndef UART_DEV_INCLUDE /* <--- keep the same name for guard across archs for compile-time sanity */\n#define UART_DEV_INCLUDE\n#define UART_FR_RXFE    (0x10)\n#define UART_FR_TXFF    (0x20)\n\n#ifdef STELLARIS\n#define UART_IM_RXIM    (0x10)\n#else\n#define UART_IM_RXIM    (0x10)\n#endif\n#define UART_IC_RXIC    (0x10)\n\n#define UART_DR(baseaddr) (*(uint32_t *)(baseaddr))\n#define UART_IR(baseaddr) (*(((uint32_t *)(baseaddr)) + 1))\n#define UART_FR(baseaddr) (*(((uint32_t *)(baseaddr))+(0x18>>2)))\n#define UART_IC(baseaddr) (*(((uint32_t *)(baseaddr))+(0x44>>2)))\n#define UART_IM(baseaddr) (*(((uint32_t *)(baseaddr))+(0x38>>2)))\n\n#define UART_RXREG UART_DR\n#define UART_TXREG UART_DR\n\nstatic inline char uart_rx(uint32_t *base)\n{\n    char byte = UART_RXREG(base);\n    return byte;\n}\n\nstatic inline int uart_poll_rx(uint32_t *base)\n{\n    return (!(UART_FR(base) & UART_FR_RXFE));\n}\n\nstatic inline void uart_enter_irq(uint32_t *base)\n{\n    UART_IC(base) = UART_IC_RXIC;\n}\n/*\nstatic inline void uart_init(uint32_t *base)\n{\n    UART_IR(base) = 0;\n    UART_IM(base) = UART_IM_RXIM;\n}\n*/\nstatic inline void uart_tx(uint32_t *base, char c)\n{\n    UART_TXREG(base) = c;\n}\n#endif\n"
  },
  {
    "path": "kernel/drivers/usb/usb_kbd.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n */\n#include \"frosted.h\"\n#include \"device.h\"\n#include \"usb.h\"\n#include \"cirbuf.h\"\n#include \"poll.h\"\n#include <unicore-mx/usbh/usbh.h>\n#include <unicore-mx/usbh/helper/ctrlreq.h>\n#include <unicore-mx/usbh/class/hid.h>\n\n#define CLASS_HID 0x03\n#define SUBCLASS_HID_BOOT 0x01\n#define PROTOCOL_HID_KEYBOARD 0x01\n#define KBD_BUF_SIZE 128\n#define KBD_FIFO_SIZE 16\n\n/* Special keys */\n\n#define CAPS_LOCK 0x39\n#define SHIFT_L   0x02\n#define SHIFT_R   0x20\n#define CTRL_L    0x01\n#define CTRL_R    0x10\n\n#define ESC       0x1B\n#define BS        0x08\n#define DEL       0x7F\n\nconst char map_num[10][2] = {\n    {'1', '!'},\n    {'2', '@'},\n    {'3', '#'},\n    {'4', '$'},\n    {'5', '%'},\n    {'6', '^'},\n    {'7', '&'},\n    {'8', '*'},\n    {'9', '('},\n    {'0', ')'}\n};\n\nconst char map_others[17][2] = {\n    {'\\n', '\\r'},\n    {ESC, ESC},\n    {BS, DEL},\n    {'\\t','\\t'},\n    {' ', ' '},\n    {'-', '_'},\n    {'=', '+'},\n    {'[', '{'},\n    {']', '}'},\n    {'\\\\', '|'},\n    {0, 0},\n    {';', ':'},\n    {'\\'', '\"'},\n    {'`', '~'},\n    {',', '<'},\n    {'.', '>'},\n    {'/', '?'},\n};\n\nconst char map_arrows[4] = { 'C', 'D', 'B', 'A' };\n\n\n\n#ifndef FALL_THROUGH\n#define FALL_THROUGH do{}while(0)\n#endif\n\nstatic int kbd_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int kbd_poll(struct fnode *fno, uint16_t events, uint16_t *revents);\nstatic int kbd_ioctl(struct fnode *fno, const uint32_t cmd, void *arg);\nstatic void usb_kbd_disconnect(struct usbh_device *dev, uint8_t bInterfaceNumber);\n\nstatic struct module mod_usbkbd = {\n    .family = FAMILY_DEV,\n    .name = \"usbkbd\",\n    .ops.open = device_open,\n    .ops.read = kbd_read,\n    .ops.ioctl = kbd_ioctl,\n    .ops.poll = kbd_poll,\n};\n\n/* Only support one keyboard for now. \n * Extend this to an array or list to \n * claim multiple keyboards.\n */\n\nstatic struct keyboard {\n    struct device *dev;\n    uint8_t iface_num, \n            iface_altset, \n            ep_number, \n            ep_size, \n            ep_interval;\n    uint8_t buf[KBD_BUF_SIZE];\n    struct  cirbuf *cfifo;\n    int     caps_lock;\n    uint8_t     mode;\n} KBD;\n\n\nstatic void kbd_data_in(const uint8_t *data, unsigned len)\n{\n    char mod = 0;\n    int i;\n    char shift;\n    char c;\n    int special = 0;\n    int escape = 0;\n\n    if (KBD.mode == K_RAW) {\n        cirbuf_writebytes(KBD.cfifo, data, len);\n        return;\n    }\n\n    if (len <= 0)\n        return;\n    mod = data[0];\n    for (i = 0; i < len -2; i++) {\n        uint8_t u = data[i + 2];\n        c = '\\0';\n        if (u == CAPS_LOCK) {\n            KBD.caps_lock = !KBD.caps_lock;\n            continue;\n        }\n        if ((mod & SHIFT_L) || (mod & SHIFT_R)) {\n            shift = (KBD.caps_lock)?'a':'A';\n            special = 1;\n        } else {\n            shift = (KBD.caps_lock)?'A':'a';\n            special = 0;\n        }\n        \n        /* Intercept CTRL */\n        if ((mod & CTRL_L) || (mod & CTRL_R)) {\n            if (u == 0x06) /* CTRL + C */\n                c = 0x03;\n            continue;\n        }\n\n        /* Letters */\n        if ((u >= 4) && (u <= 0x1d))\n            c = (u - 4) + shift;\n\n        /* Numbers and co. */\n        else if ((u >= 0x1e) && (u <= 0x27))\n            c = map_num[u - 0x1e][special];\n\n        /* Other printable symbols */\n        else if ((u >= 0x28) && (u <= 0x38))\n            c = map_others[u - 0x28][special];\n        \n        /* Arrow keys */\n        if ((u >= 0x4f) && (u <= 0x52)) {\n            escape = 1;\n            c = map_arrows[u - 0x4f];\n        }\n\n        /* load result in buffer */\n        if (c) {\n            mutex_lock(KBD.dev->mutex);\n            if (escape) {\n                cirbuf_writebyte(KBD.cfifo, ESC);\n                cirbuf_writebyte(KBD.cfifo, '[');\n            }\n            cirbuf_writebyte(KBD.cfifo, c);\n            task_resume(KBD.dev->task);\n            mutex_unlock(KBD.dev->mutex);\n        }\n    }\n}\n\nstatic void endpoint_read_cb (const usbh_transfer *transfer,\n\tusbh_transfer_status status, usbh_urb_id urb_id)\n{\n\t(void) urb_id;\n    /* TODO: add a default for unexpected error. Delete device. */\n\n\tswitch (status) {\n\tcase USBH_SUCCESS:\n\t\tkbd_data_in(transfer->data, transfer->transferred);\n        FALL_THROUGH;\n\tcase USBH_ERR_TIMEOUT:\n        FALL_THROUGH;\n\tcase USBH_ERR_IO:\n\t\t/* resubmit! */\n\t\tusbh_transfer_submit(transfer);\n        break;\n\t}\n}\n\nstatic void read_data_from_keyboard(usbh_device *dev)\n{\n\tusbh_transfer ep_transfer = {\n\t\t.device = dev,\n\t\t.ep_type = USBH_EP_INTERRUPT,\n\t\t.ep_addr = KBD.ep_number,\n\t\t.ep_size = KBD.ep_size,\n\t\t.interval = KBD.ep_interval,\n\t\t.data = KBD.buf,\n\t\t.length = KBD.ep_size,\n\t\t.flags = USBH_FLAG_NONE,\n\t\t.timeout = 250,\n\t\t.callback = endpoint_read_cb,\n\t};\n\tusbh_transfer_submit(&ep_transfer);\n}\n\n\n\nstatic void devfile_create(void) \n{\n    char name[5] = \"kbd0\";\n    struct fnode *devfs = fno_search(\"/dev\");\n    if (!devfs)\n        return;\n    KBD.dev = device_fno_init(&mod_usbkbd, name, devfs, FL_TTY, &KBD);\n}\n\nstatic void after_set_idle(const usbh_transfer *transfer,\n\tusbh_transfer_status status, usbh_urb_id urb_id)\n{\n\t(void) urb_id;\n    (void) status;\n\tread_data_from_keyboard(transfer->device);\n}\n\nstatic void after_set_protocol_boot(const usbh_transfer *transfer,\n\tusbh_transfer_status status, usbh_urb_id urb_id)\n{\n\t(void) urb_id;\n\n\tif (status != USBH_SUCCESS) {\n\t\treturn;\n\t}\n    usbh_hid_set_idle(transfer->device, 0, 0, KBD.iface_num, after_set_idle);\n}\n\nstatic void after_interface_set(const usbh_transfer *transfer,\n\tusbh_transfer_status status, usbh_urb_id urb_id)\n{\n\t(void) urb_id;\n    (void) status;\n\tusbh_hid_set_protocol(transfer->device, USB_REQ_HID_PROTOCOL_BOOT,\n\t\tKBD.iface_num, after_set_protocol_boot);\n}\n\nstatic void after_config_set(const usbh_transfer *transfer,\n\tusbh_transfer_status status, usbh_urb_id urb_id)\n{\n\t(void) urb_id;\n\n\tif (status != USBH_SUCCESS) {\n\t\treturn;\n\t}\n\tusbh_ctrlreq_set_interface(transfer->device, KBD.iface_num,\n\t\t\tKBD.iface_altset, after_interface_set);\n}\n\nstatic void usb_kbd_probe( struct usbh_device *dev,\n        const struct usb_device_descriptor *ddesc,\n        const struct usb_config_descriptor *cfg)\n{\n    uint8_t class = ddesc->bDeviceClass;\n    uint8_t subclass = ddesc->bDeviceSubClass;\n    uint8_t protocol = ddesc->bDeviceProtocol;\n    int ifnum = -1;\n\tuint8_t  *ptr = ((uint8_t *)cfg) + cfg->bLength;\n\tint len = cfg->wTotalLength - cfg->bLength;\n\tstruct usb_interface_descriptor *iface_interest = NULL;\n\tstruct usb_endpoint_descriptor *ep_interest = NULL;\n\n    /* Check device configurations */\n    if (ddesc->bNumConfigurations < 1)\n        return;\n\n    /* Check class, subclass, protocol for direct claim */\n    if ((class == CLASS_HID) || (subclass == SUBCLASS_HID_BOOT) || (protocol == PROTOCOL_HID_KEYBOARD)) {\n        /* TODO: claim */\n\n        return;\n    }\n         \n\n    if (cfg->bLength < 4) {\n        /* Descriptor is too small. */\n        return;\n    }\n\n\twhile (len > 0) {\n        switch (ptr[1]) {\n            case USB_DT_INTERFACE: \n                {\n                    struct usb_interface_descriptor *iface = \n                        (struct usb_interface_descriptor *)ptr;\n                    if (iface->bInterfaceClass == CLASS_HID &&\n                            iface->bInterfaceSubClass == SUBCLASS_HID_BOOT &&\n                            iface->bInterfaceProtocol == PROTOCOL_HID_KEYBOARD &&\n                            iface->bNumEndpoints) {\n                        iface_interest = iface;\n                    }\n\n                    ep_interest = NULL;\n                } break;\n            case USB_DT_ENDPOINT: \n                {\n                    struct usb_endpoint_descriptor *ep = (struct usb_endpoint_descriptor *)ptr;\n                    if (iface_interest == NULL) {\n                        break;\n                    }\n                    if ((ep->bmAttributes & USB_ENDPOINT_ATTR_TYPE) ==\n                            USB_ENDPOINT_ATTR_INTERRUPT &&\n                            (ep->bEndpointAddress & 0x80)) {\n                        ep_interest = ep;\n                    }\n                } break;\n        } /* end switch/case */\n\n\t\tif ((iface_interest != NULL) && (ep_interest != NULL)) {\n\t\t\tbreak;\n\t\t}\n\t\tptr += ptr[0];\n\t\tlen -= ptr[0];\n\t}\n\n    if ((iface_interest == NULL) || (ep_interest == NULL)) {\n        return;\n    }\n\tKBD.iface_num = iface_interest->bInterfaceNumber;\n\tKBD.iface_altset = iface_interest->bAlternateSetting;\n\tKBD.ep_number = ep_interest->bEndpointAddress;\n\tKBD.ep_size = ep_interest->wMaxPacketSize;\n\tKBD.ep_interval = ep_interest->bInterval;\n    if (usb_host_claim_interface(&mod_usbkbd, dev, KBD.iface_num, usb_kbd_disconnect) < 0) {\n        /* Failed to claim interface. */\n        return;\n    }\n\tusbh_ctrlreq_set_config(dev, cfg->bConfigurationValue,\n\t\t\tafter_config_set);\n    KBD.cfifo = cirbuf_create(KBD_FIFO_SIZE);\n    devfile_create();\n    \n}\n\nstatic void usb_kbd_disconnect(struct usbh_device *dev, uint8_t bInterfaceNumber)\n{\n    /* TODO: delete char device. */\n    return; \n}\n\nvoid usb_kbd_init(void) \n{\n    KBD.mode = K_XLATE; \n    register_module(&mod_usbkbd);\n    usb_host_driver_register(&mod_usbkbd, usb_kbd_probe);\n}\n\nstatic int kbd_read(struct fnode *fno, void *buf, unsigned int len) \n{\n    int ret = 0;\n    char *cbuf = (char *)buf;\n    if (len == 0)\n        return 0;\n    KBD.dev->task = this_task();\n    mutex_lock(KBD.dev->mutex);\n    if (cirbuf_bytesinuse(KBD.cfifo) > 0) {\n        ret = cirbuf_readbytes(KBD.cfifo, buf, len);\n    } else {\n        task_suspend();\n        ret = SYS_CALL_AGAIN;\n    }\n    mutex_unlock(KBD.dev->mutex);\n    return ret;\n}\n\nstatic int kbd_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    int ret = 0;\n    KBD.dev->task = this_task();\n    mutex_lock(KBD.dev->mutex);\n    if ((events == POLLIN) && (cirbuf_bytesinuse(KBD.cfifo) > 0)) {\n        *revents |= POLLIN;\n        ret = 1;\n    }\n    mutex_unlock(KBD.dev->mutex);\n    return ret;\n}\n\nstatic int kbd_ioctl(struct fnode *fno, const uint32_t cmd, void *arg)\n{\n    if (cmd == KDSKBMODE) {\n        mutex_lock(KBD.dev->mutex);\n        uint32_t *mode = (uint32_t *)arg;\n        uint8_t newmode = (*mode) & 0xFF;\n        uint8_t c;\n        if (newmode != KBD.mode) {\n            while(cirbuf_bytesinuse(KBD.cfifo) > 0)\n                cirbuf_readbyte(KBD.cfifo, &c);\n            KBD.mode = newmode;\n        }\n        mutex_unlock(KBD.dev->mutex);\n    } else {\n        return -EINVAL; \n    }\n}\n"
  },
  {
    "path": "kernel/drivers/usb/usbh_drivers.h",
    "content": "#include \"frosted.h\"\n#include \"device.h\"\n#ifndef USBH_DRIVERS_H\n#define USBH_DRIVERS_H\n\n/* Put your driver initalizers here */\n\nextern void usb_kbd_init(void);\n\n\nstatic inline void usbh_drivers_init(void)\n{\n    #ifdef CONFIG_DEV_USBH_KBD\n    usb_kbd_init();\n    #endif\n}\n\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/usb.h",
    "content": "#ifndef INC_USB\n#define INC_USB\n#include \"frosted.h\"\n#include \"gpio.h\"\n#include <unicore-mx/usbd/usbd.h>\n#include <unicore-mx/usb/class/cdc.h>\n#include <unicore-mx/cm3/scb.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/usbh/usbh.h>\n\n#define USB_DEV_FS 0\n#define USB_DEV_HS 1\n\n#define USB_MODE_GUEST 1\n#define USB_MODE_HOST  2\n\ntypedef void (*usb_host_driver_probe_callback)(\n        struct usbh_device *dev,\n        const struct usb_device_descriptor *device_desc,\n        const struct usb_config_descriptor *config_desc);\n\ntypedef void (*usb_host_interface_removed_callback)(\n    struct usbh_device *dev, uint8_t bInterfaceNumber);\n\nint usb_host_driver_register(struct module *owner,\n        usb_host_driver_probe_callback probe);\n\nint usb_host_claim_interface(struct module *owner,\n        usbh_device *dev, uint8_t bInterfaceNumber,\n        usb_host_interface_removed_callback removed);\n\nint usb_host_release_interface(usbh_device *dev,\n        uint8_t bInterfaceNumber);\n\nstruct usb_pio_config_fs {\n    struct gpio_config pio_vbus;\n    struct gpio_config pio_dm;\n    struct gpio_config pio_dp;\n    struct gpio_config pio_phy;\n};\n\nstruct usb_pio_config_hs {\n    struct gpio_config ulpi_data[8];\n    struct gpio_config ulpi_clk;\n    struct gpio_config ulpi_dir;\n    struct gpio_config ulpi_next;\n    struct gpio_config ulpi_step;\n};\n\nstruct usb_config {\n    unsigned int dev_type;\n    unsigned int otg_mode;\n\n    union usb_pio_config {\n        struct usb_pio_config_fs *fs;\n        struct usb_pio_config_hs *hs;\n    } pio;\n};\n\n#ifdef CONFIG_DEVUSB\n    int usb_init(struct usb_config *conf);\n    int usbdev_start(usbd_device **_usbd_dev, unsigned int dev,\n          const struct usbd_info *info);\n#else\n#  define usb_init(x) ((-ENOENT))\n#  define usbdev_start(...) ((-ENOENT))\n#endif\n\n\n#ifdef CONFIG_DEV_USBETH\n    int usb_ethernet_init(unsigned int dev);\n#else\n#  define usb_ethernet_init(x) ((-ENOENT))\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/drivers/xadow_LED_5x7.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera <root@danielinux.net>\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include <stdint.h>\n#include \"cirbuf.h\"\n#include \"dma.h\"\n#include \"cirbuf.h\"\n#include \"i2c.h\"\n\n#define XADOW_LED_I2C_ADDR (0x21 << 1)\n\n#define DISP_CHAR_5X7                0x80\n#define DISP_STRING                  0x81\n#define SET_DISP_ORIENTATION         0x82\n#define POWER_DOWN                   0x83\n#define DISP_PIC                     0x84\n#define DISP_DATA                    0x85\n\nstruct dev_matrix {\n    struct i2c_slave i2c;\n    struct device *dev;\n    uint8_t i2c_data;\n    uint8_t buf[20];\n    int update;\n} Matrix;\n\nstatic struct task *kt = NULL;\n\n\n\n/* Module description */\nstatic int xadow_led_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    return 0;\n}\n\n\nstatic int xadow_led_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    memset(Matrix.buf, 0, 20);\n    if (len > 17)\n        len = 17;\n    Matrix.buf[0] = len;\n    if (len > 0) {\n        memcpy(Matrix.buf + 1, buf, len);\n    }\n    Matrix.buf[len + 1] = 0;\n    Matrix.buf[len + 2] = 120;\n\n    Matrix.update = len + 3;\n    return len;\n}\n\nstatic void xadow_led_task(void *arg)\n{\n    (void)arg;\n    int r;\n    Matrix.update = 0;\n    while(1<2) {\n        if (Matrix.update) {\n            r = i2c_kthread_write(&Matrix.i2c, DISP_STRING, Matrix.buf, Matrix.update);\n            Matrix.update = 0;\n        }\n        kthread_yield();\n    }\n}\n\nstatic int xadow_led_open(const char *path, int flags)\n{\n    struct fnode *f = fno_search(path);\n    if (!f)\n        return -1;\n    kt = kthread_create(xadow_led_task, NULL);\n    return task_filedesc_add(f);\n}\n\nstatic int xadow_led_close(struct fnode *f)\n{\n    if (kt) {\n        kthread_cancel(kt);\n        kt = NULL;\n    }\n    return 0;\n}\n\nstatic struct module mod_devmatrix = {\n    .family = FAMILY_FILE,\n    .name = \"matrix\",\n    .ops.open = xadow_led_open,\n    .ops.read = xadow_led_read,\n    .ops.write = xadow_led_write,\n    .ops.close = xadow_led_close\n};\n\n\nint xadow_led_init(uint32_t bus)\n{\n    int i;\n    struct fnode *devdir = fno_search(\"/dev\");\n    if (!devdir)\n        return -ENOENT;\n    memset(&Matrix, 0, sizeof(struct dev_matrix));\n    Matrix.dev = device_fno_init(&mod_devmatrix, \"matrix\", devdir, 0, &Matrix);\n\n\n    /* Populate i2c_slave struct */\n    Matrix.i2c.bus = bus;\n    Matrix.i2c.address = XADOW_LED_I2C_ADDR;\n    //kthread_create(xadow_led_task, NULL);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/fonts/cga_8x8.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n *      Automatically generated using CGA 8x8 font by EPTO\n *\n */\n\nconst unsigned char fb_font[256][8] = {\n    { //Ascii 0\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 1\n        0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, \n    },\n    { //Ascii 2\n        0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, \n    },\n    { //Ascii 3\n        0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, \n    },\n    { //Ascii 4\n        0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, \n    },\n    { //Ascii 5\n        0x38, 0x7C, 0x38, 0xFE, 0xFE, 0xD6, 0x10, 0x38, \n    },\n    { //Ascii 6\n        0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x10, 0x38, \n    },\n    { //Ascii 7\n        0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, \n    },\n    { //Ascii 8\n        0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, \n    },\n    { //Ascii 9\n        0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, \n    },\n    { //Ascii 10\n        0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, \n    },\n    { //Ascii 11\n        0x0F, 0x03, 0x05, 0x7D, 0x84, 0x84, 0x84, 0x78, \n    },\n    { //Ascii 12\n        0x3C, 0x42, 0x42, 0x42, 0x3C, 0x18, 0x7E, 0x18, \n    },\n    { //Ascii 13\n        0x3F, 0x21, 0x3F, 0x20, 0x20, 0x60, 0xE0, 0xC0, \n    },\n    { //Ascii 14\n        0x3F, 0x21, 0x3F, 0x21, 0x23, 0x67, 0xE6, 0xC0, \n    },\n    { //Ascii 15\n        0x18, 0xDB, 0x3C, 0xE7, 0xE7, 0x3C, 0xDB, 0x18, \n    },\n    { //Ascii 16\n        0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, \n    },\n    { //Ascii 17\n        0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, \n    },\n    { //Ascii 18\n        0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, \n    },\n    { //Ascii 19\n        0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x24, 0x00, \n    },\n    { //Ascii 20\n        0x7F, 0x92, 0x92, 0x72, 0x12, 0x12, 0x12, 0x00, \n    },\n    { //Ascii 21\n        0x3E, 0x63, 0x38, 0x44, 0x44, 0x38, 0xCC, 0x78, \n    },\n    { //Ascii 22\n        0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, \n    },\n    { //Ascii 23\n        0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, \n    },\n    { //Ascii 24\n        0x10, 0x38, 0x7C, 0x54, 0x10, 0x10, 0x10, 0x00, \n    },\n    { //Ascii 25\n        0x10, 0x10, 0x10, 0x54, 0x7C, 0x38, 0x10, 0x00, \n    },\n    { //Ascii 26\n        0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, \n    },\n    { //Ascii 27\n        0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, \n    },\n    { //Ascii 28\n        0x00, 0x00, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, \n    },\n    { //Ascii 29\n        0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, \n    },\n    { //Ascii 30\n        0x00, 0x10, 0x38, 0x7C, 0xFE, 0xFE, 0x00, 0x00, \n    },\n    { //Ascii 31\n        0x00, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, \n    },\n    { //Ascii 32\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 33\n        0x10, 0x38, 0x38, 0x10, 0x10, 0x00, 0x10, 0x00, \n    },\n    { //Ascii 34\n        0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 35\n        0x24, 0x24, 0x7E, 0x24, 0x7E, 0x24, 0x24, 0x00, \n    },\n    { //Ascii 36\n        0x18, 0x3E, 0x40, 0x3C, 0x02, 0x7C, 0x18, 0x00, \n    },\n    { //Ascii 37\n        0x00, 0x62, 0x64, 0x08, 0x10, 0x26, 0x46, 0x00, \n    },\n    { //Ascii 38\n        0x30, 0x48, 0x30, 0x56, 0x88, 0x88, 0x76, 0x00, \n    },\n    { //Ascii 39\n        0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 40\n        0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00, \n    },\n    { //Ascii 41\n        0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, \n    },\n    { //Ascii 42\n        0x00, 0x44, 0x38, 0xFE, 0x38, 0x44, 0x00, 0x00, \n    },\n    { //Ascii 43\n        0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, \n    },\n    { //Ascii 44\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, \n    },\n    { //Ascii 45\n        0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 46\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, \n    },\n    { //Ascii 47\n        0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, \n    },\n    { //Ascii 48\n        0x3C, 0x42, 0x46, 0x4A, 0x52, 0x62, 0x3C, 0x00, \n    },\n    { //Ascii 49\n        0x10, 0x30, 0x50, 0x10, 0x10, 0x10, 0x7C, 0x00, \n    },\n    { //Ascii 50\n        0x3C, 0x42, 0x02, 0x0C, 0x30, 0x42, 0x7E, 0x00, \n    },\n    { //Ascii 51\n        0x3C, 0x42, 0x02, 0x1C, 0x02, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 52\n        0x08, 0x18, 0x28, 0x48, 0xFE, 0x08, 0x1C, 0x00, \n    },\n    { //Ascii 53\n        0x7E, 0x40, 0x7C, 0x02, 0x02, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 54\n        0x1C, 0x20, 0x40, 0x7C, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 55\n        0x7E, 0x42, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00, \n    },\n    { //Ascii 56\n        0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 57\n        0x3C, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x38, 0x00, \n    },\n    { //Ascii 58\n        0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, \n    },\n    { //Ascii 59\n        0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, \n    },\n    { //Ascii 60\n        0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, \n    },\n    { //Ascii 61\n        0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, \n    },\n    { //Ascii 62\n        0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, \n    },\n    { //Ascii 63\n        0x3C, 0x42, 0x02, 0x04, 0x08, 0x00, 0x08, 0x00, \n    },\n    { //Ascii 64\n        0x3C, 0x42, 0x5E, 0x52, 0x5E, 0x40, 0x3C, 0x00, \n    },\n    { //Ascii 65\n        0x18, 0x24, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x00, \n    },\n    { //Ascii 66\n        0x7C, 0x22, 0x22, 0x3C, 0x22, 0x22, 0x7C, 0x00, \n    },\n    { //Ascii 67\n        0x1C, 0x22, 0x40, 0x40, 0x40, 0x22, 0x1C, 0x00, \n    },\n    { //Ascii 68\n        0x78, 0x24, 0x22, 0x22, 0x22, 0x24, 0x78, 0x00, \n    },\n    { //Ascii 69\n        0x7E, 0x22, 0x28, 0x38, 0x28, 0x22, 0x7E, 0x00, \n    },\n    { //Ascii 70\n        0x7E, 0x22, 0x28, 0x38, 0x28, 0x20, 0x70, 0x00, \n    },\n    { //Ascii 71\n        0x1C, 0x22, 0x40, 0x40, 0x4E, 0x22, 0x1E, 0x00, \n    },\n    { //Ascii 72\n        0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00, \n    },\n    { //Ascii 73\n        0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, \n    },\n    { //Ascii 74\n        0x0E, 0x04, 0x04, 0x04, 0x44, 0x44, 0x38, 0x00, \n    },\n    { //Ascii 75\n        0x62, 0x24, 0x28, 0x30, 0x28, 0x24, 0x63, 0x00, \n    },\n    { //Ascii 76\n        0x70, 0x20, 0x20, 0x20, 0x20, 0x22, 0x7E, 0x00, \n    },\n    { //Ascii 77\n        0x63, 0x55, 0x49, 0x41, 0x41, 0x41, 0x41, 0x00, \n    },\n    { //Ascii 78\n        0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x42, 0x00, \n    },\n    { //Ascii 79\n        0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, \n    },\n    { //Ascii 80\n        0x7C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x70, 0x00, \n    },\n    { //Ascii 81\n        0x3C, 0x42, 0x42, 0x42, 0x4A, 0x3C, 0x03, 0x00, \n    },\n    { //Ascii 82\n        0x7C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x72, 0x00, \n    },\n    { //Ascii 83\n        0x3C, 0x42, 0x40, 0x3C, 0x02, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 84\n        0x7F, 0x49, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, \n    },\n    { //Ascii 85\n        0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 86\n        0x41, 0x41, 0x41, 0x41, 0x22, 0x14, 0x08, 0x00, \n    },\n    { //Ascii 87\n        0x41, 0x41, 0x41, 0x49, 0x49, 0x49, 0x36, 0x00, \n    },\n    { //Ascii 88\n        0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41, 0x00, \n    },\n    { //Ascii 89\n        0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x1C, 0x00, \n    },\n    { //Ascii 90\n        0x7F, 0x42, 0x04, 0x08, 0x10, 0x21, 0x7F, 0x00, \n    },\n    { //Ascii 91\n        0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x78, 0x00, \n    },\n    { //Ascii 92\n        0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, \n    },\n    { //Ascii 93\n        0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, \n    },\n    { //Ascii 94\n        0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 95\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, \n    },\n    { //Ascii 96\n        0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 97\n        0x00, 0x00, 0x3C, 0x02, 0x3E, 0x42, 0x3F, 0x00, \n    },\n    { //Ascii 98\n        0x60, 0x20, 0x20, 0x2E, 0x31, 0x31, 0x2E, 0x00, \n    },\n    { //Ascii 99\n        0x00, 0x00, 0x3C, 0x42, 0x40, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 100\n        0x06, 0x02, 0x02, 0x3A, 0x46, 0x46, 0x3B, 0x00, \n    },\n    { //Ascii 101\n        0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x3C, 0x00, \n    },\n    { //Ascii 102\n        0x0C, 0x12, 0x10, 0x38, 0x10, 0x10, 0x38, 0x00, \n    },\n    { //Ascii 103\n        0x00, 0x00, 0x3D, 0x42, 0x42, 0x3E, 0x02, 0x7C, \n    },\n    { //Ascii 104\n        0x60, 0x20, 0x2C, 0x32, 0x22, 0x22, 0x62, 0x00, \n    },\n    { //Ascii 105\n        0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00, \n    },\n    { //Ascii 106\n        0x02, 0x00, 0x06, 0x02, 0x02, 0x42, 0x42, 0x3C, \n    },\n    { //Ascii 107\n        0x60, 0x20, 0x24, 0x28, 0x30, 0x28, 0x26, 0x00, \n    },\n    { //Ascii 108\n        0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, \n    },\n    { //Ascii 109\n        0x00, 0x00, 0x76, 0x49, 0x49, 0x49, 0x49, 0x00, \n    },\n    { //Ascii 110\n        0x00, 0x00, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x00, \n    },\n    { //Ascii 111\n        0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 112\n        0x00, 0x00, 0x6C, 0x32, 0x32, 0x2C, 0x20, 0x70, \n    },\n    { //Ascii 113\n        0x00, 0x00, 0x36, 0x4C, 0x4C, 0x34, 0x04, 0x0E, \n    },\n    { //Ascii 114\n        0x00, 0x00, 0x6C, 0x32, 0x22, 0x20, 0x70, 0x00, \n    },\n    { //Ascii 115\n        0x00, 0x00, 0x3E, 0x40, 0x3C, 0x02, 0x7C, 0x00, \n    },\n    { //Ascii 116\n        0x10, 0x10, 0x7C, 0x10, 0x10, 0x12, 0x0C, 0x00, \n    },\n    { //Ascii 117\n        0x00, 0x00, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, \n    },\n    { //Ascii 118\n        0x00, 0x00, 0x41, 0x41, 0x22, 0x14, 0x08, 0x00, \n    },\n    { //Ascii 119\n        0x00, 0x00, 0x41, 0x49, 0x49, 0x49, 0x36, 0x00, \n    },\n    { //Ascii 120\n        0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, \n    },\n    { //Ascii 121\n        0x00, 0x00, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x7C, \n    },\n    { //Ascii 122\n        0x00, 0x00, 0x7C, 0x08, 0x10, 0x20, 0x7C, 0x00, \n    },\n    { //Ascii 123\n        0x0C, 0x10, 0x10, 0x60, 0x10, 0x10, 0x0C, 0x00, \n    },\n    { //Ascii 124\n        0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, \n    },\n    { //Ascii 125\n        0x30, 0x08, 0x08, 0x06, 0x08, 0x08, 0x30, 0x00, \n    },\n    { //Ascii 126\n        0x32, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 127\n        0x00, 0x08, 0x14, 0x22, 0x41, 0x41, 0x7F, 0x00, \n    },\n    { //Ascii 128\n        0x3C, 0x42, 0x40, 0x42, 0x3C, 0x0C, 0x02, 0x3C, \n    },\n    { //Ascii 129\n        0x00, 0x44, 0x00, 0x44, 0x44, 0x44, 0x3E, 0x00, \n    },\n    { //Ascii 130\n        0x0C, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x3C, 0x00, \n    },\n    { //Ascii 131\n        0x3C, 0x42, 0x38, 0x04, 0x3C, 0x44, 0x3E, 0x00, \n    },\n    { //Ascii 132\n        0x42, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3E, 0x00, \n    },\n    { //Ascii 133\n        0x30, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3E, 0x00, \n    },\n    { //Ascii 134\n        0x10, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3E, 0x00, \n    },\n    { //Ascii 135\n        0x00, 0x00, 0x3C, 0x40, 0x40, 0x3C, 0x06, 0x1C, \n    },\n    { //Ascii 136\n        0x3C, 0x42, 0x3C, 0x42, 0x7E, 0x40, 0x3C, 0x00, \n    },\n    { //Ascii 137\n        0x42, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x3C, 0x00, \n    },\n    { //Ascii 138\n        0x30, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x3C, 0x00, \n    },\n    { //Ascii 139\n        0x24, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, \n    },\n    { //Ascii 140\n        0x7C, 0x82, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00, \n    },\n    { //Ascii 141\n        0x30, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, \n    },\n    { //Ascii 142\n        0x42, 0x18, 0x24, 0x42, 0x7E, 0x42, 0x42, 0x00, \n    },\n    { //Ascii 143\n        0x18, 0x18, 0x00, 0x3C, 0x42, 0x7E, 0x42, 0x00, \n    },\n    { //Ascii 144\n        0x0C, 0x00, 0x7C, 0x20, 0x38, 0x20, 0x7C, 0x00, \n    },\n    { //Ascii 145\n        0x00, 0x00, 0x33, 0x0C, 0x3F, 0x44, 0x3B, 0x00, \n    },\n    { //Ascii 146\n        0x1F, 0x24, 0x44, 0x7F, 0x44, 0x44, 0x47, 0x00, \n    },\n    { //Ascii 147\n        0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 148\n        0x00, 0x42, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 149\n        0x20, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 150\n        0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 151\n        0x20, 0x10, 0x00, 0x42, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 152\n        0x00, 0x42, 0x00, 0x42, 0x42, 0x3E, 0x02, 0x3C, \n    },\n    { //Ascii 153\n        0x42, 0x18, 0x24, 0x42, 0x42, 0x24, 0x18, 0x00, \n    },\n    { //Ascii 154\n        0x42, 0x00, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 155\n        0x08, 0x08, 0x3E, 0x40, 0x40, 0x3E, 0x08, 0x08, \n    },\n    { //Ascii 156\n        0x18, 0x24, 0x20, 0x70, 0x20, 0x42, 0x7C, 0x00, \n    },\n    { //Ascii 157\n        0x44, 0x28, 0x7C, 0x10, 0x7C, 0x10, 0x10, 0x00, \n    },\n    { //Ascii 158\n        0xF8, 0x4C, 0x78, 0x44, 0x4F, 0x44, 0x45, 0xE6, \n    },\n    { //Ascii 159\n        0x1C, 0x12, 0x10, 0x7C, 0x10, 0x10, 0x90, 0x60, \n    },\n    { //Ascii 160\n        0x0C, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3E, 0x00, \n    },\n    { //Ascii 161\n        0x0C, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, \n    },\n    { //Ascii 162\n        0x04, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 163\n        0x00, 0x04, 0x08, 0x42, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 164\n        0x32, 0x4C, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x00, \n    },\n    { //Ascii 165\n        0x34, 0x4C, 0x00, 0x62, 0x52, 0x4A, 0x46, 0x00, \n    },\n    { //Ascii 166\n        0x3C, 0x44, 0x44, 0x3E, 0x00, 0x7E, 0x00, 0x00, \n    },\n    { //Ascii 167\n        0x38, 0x44, 0x44, 0x38, 0x00, 0x7C, 0x00, 0x00, \n    },\n    { //Ascii 168\n        0x10, 0x00, 0x10, 0x20, 0x40, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 169\n        0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x00, 0x00, \n    },\n    { //Ascii 170\n        0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x00, 0x00, \n    },\n    { //Ascii 171\n        0x42, 0xC4, 0x48, 0xF6, 0x29, 0x43, 0x8C, 0x1F, \n    },\n    { //Ascii 172\n        0x42, 0xC4, 0x4A, 0xF6, 0x2A, 0x5F, 0x82, 0x02, \n    },\n    { //Ascii 173\n        0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, \n    },\n    { //Ascii 174\n        0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00, \n    },\n    { //Ascii 175\n        0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, \n    },\n    { //Ascii 176\n        0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, \n    },\n    { //Ascii 177\n        0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, \n    },\n    { //Ascii 178\n        0xDB, 0x77, 0xDB, 0xEE, 0xDB, 0x77, 0xDB, 0xEE, \n    },\n    { //Ascii 179\n        0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 180\n        0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 181\n        0x10, 0x10, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 182\n        0x14, 0x14, 0x14, 0x14, 0xF4, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 183\n        0x00, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 184\n        0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 185\n        0x14, 0x14, 0xF4, 0x04, 0xF4, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 186\n        0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 187\n        0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 188\n        0x14, 0x14, 0xF4, 0x04, 0xFC, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 189\n        0x14, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 190\n        0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 191\n        0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 192\n        0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 193\n        0x10, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 194\n        0x00, 0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 195\n        0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 196\n        0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 197\n        0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 198\n        0x10, 0x10, 0x1F, 0x10, 0x1F, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 199\n        0x14, 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 200\n        0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 201\n        0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 202\n        0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 203\n        0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 204\n        0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 205\n        0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 206\n        0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 207\n        0x10, 0x10, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 208\n        0x14, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 209\n        0x00, 0x00, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 210\n        0x00, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 211\n        0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 212\n        0x10, 0x10, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 213\n        0x00, 0x00, 0x1F, 0x10, 0x1F, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 214\n        0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 215\n        0x14, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x14, 0x14, \n    },\n    { //Ascii 216\n        0x10, 0x10, 0xFF, 0x10, 0xFF, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 217\n        0x10, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 218\n        0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 219\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n    },\n    { //Ascii 220\n        0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \n    },\n    { //Ascii 221\n        0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, \n    },\n    { //Ascii 222\n        0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, \n    },\n    { //Ascii 223\n        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 224\n        0x00, 0x00, 0x31, 0x4A, 0x44, 0x4A, 0x31, 0x00, \n    },\n    { //Ascii 225\n        0x00, 0x3C, 0x42, 0x7C, 0x42, 0x7C, 0x40, 0x40, \n    },\n    { //Ascii 226\n        0x00, 0x7E, 0x42, 0x40, 0x40, 0x40, 0x40, 0x00, \n    },\n    { //Ascii 227\n        0x00, 0x3F, 0x54, 0x14, 0x14, 0x14, 0x14, 0x00, \n    },\n    { //Ascii 228\n        0x7E, 0x42, 0x20, 0x18, 0x20, 0x42, 0x7E, 0x00, \n    },\n    { //Ascii 229\n        0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x30, 0x00, \n    },\n    { //Ascii 230\n        0x00, 0x44, 0x44, 0x44, 0x7A, 0x40, 0x40, 0x80, \n    },\n    { //Ascii 231\n        0x00, 0x33, 0x4C, 0x08, 0x08, 0x08, 0x08, 0x00, \n    },\n    { //Ascii 232\n        0x7C, 0x10, 0x38, 0x44, 0x44, 0x38, 0x10, 0x7C, \n    },\n    { //Ascii 233\n        0x18, 0x24, 0x42, 0x7E, 0x42, 0x24, 0x18, 0x00, \n    },\n    { //Ascii 234\n        0x18, 0x24, 0x42, 0x42, 0x24, 0x24, 0x66, 0x00, \n    },\n    { //Ascii 235\n        0x1C, 0x20, 0x18, 0x3C, 0x42, 0x42, 0x3C, 0x00, \n    },\n    { //Ascii 236\n        0x00, 0x62, 0x95, 0x89, 0x95, 0x62, 0x00, 0x00, \n    },\n    { //Ascii 237\n        0x02, 0x04, 0x3C, 0x4A, 0x52, 0x3C, 0x40, 0x80, \n    },\n    { //Ascii 238\n        0x0C, 0x10, 0x20, 0x3C, 0x20, 0x10, 0x0C, 0x00, \n    },\n    { //Ascii 239\n        0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, \n    },\n    { //Ascii 240\n        0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, \n    },\n    { //Ascii 241\n        0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x7C, 0x00, \n    },\n    { //Ascii 242\n        0x10, 0x08, 0x04, 0x08, 0x10, 0x00, 0x7E, 0x00, \n    },\n    { //Ascii 243\n        0x08, 0x10, 0x20, 0x10, 0x08, 0x00, 0x7E, 0x00, \n    },\n    { //Ascii 244\n        0x0C, 0x12, 0x12, 0x10, 0x10, 0x10, 0x10, 0x10, \n    },\n    { //Ascii 245\n        0x10, 0x10, 0x10, 0x10, 0x10, 0x90, 0x90, 0x60, \n    },\n    { //Ascii 246\n        0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, \n    },\n    { //Ascii 247\n        0x00, 0x32, 0x4C, 0x00, 0x32, 0x4C, 0x00, 0x00, \n    },\n    { //Ascii 248\n        0x30, 0x48, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 249\n        0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 250\n        0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 251\n        0x0F, 0x08, 0x08, 0x08, 0x08, 0xC8, 0x28, 0x18, \n    },\n    { //Ascii 252\n        0x78, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 253\n        0x30, 0x48, 0x10, 0x20, 0x78, 0x00, 0x00, 0x00, \n    },\n    { //Ascii 254\n        0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, \n    },\n    { //Ascii 255\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n    },\n\n};\n"
  },
  {
    "path": "kernel/fonts/palette_256_xterm.c",
    "content": "#include <stdint.h>\n\nconst uint32_t xterm_cmap[256] = {\n    0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xC0C0C0,\n    0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF,\n    0x000000, 0x00005F, 0x000087, 0x0000AF, 0x0000D7, 0x0000FF, 0x005F00, 0x005F5F,\n    0x005F87, 0x005FAF, 0x005FD7, 0x005FFF, 0x008700, 0x00875F, 0x008787, 0x0087AF,\n    0x0087D7, 0x0087FF, 0x00AF00, 0x00AF5F, 0x00AF87, 0x00AFAF, 0x00AFD7, 0x00AFFF,\n    0x00D700, 0x00D75F, 0x00D787, 0x00D7AF, 0x00D7D7, 0x00D7FF, 0x00FF00, 0x00FF5F,\n    0x00FF87, 0x00FFAF, 0x00FFD7, 0x00FFFF, 0x5F0000, 0x5F005F, 0x5F0087, 0x5F00AF,\n    0x5F00D7, 0x5F00FF, 0x5F5F00, 0x5F5F5F, 0x5F5F87, 0x5F5FAF, 0x5F5FD7, 0x5F5FFF,\n    0x5F8700, 0x5F875F, 0x5F8787, 0x5F87AF, 0x5F87D7, 0x5F87FF, 0x5FAF00, 0x5FAF5F,\n    0x5FAF87, 0x5FAFAF, 0x5FAFD7, 0x5FAFFF, 0x5FD700, 0x5FD75F, 0x5FD787, 0x5FD7AF,\n    0x5FD7D7, 0x5FD7FF, 0x5FFF00, 0x5FFF5F, 0x5FFF87, 0x5FFFAF, 0x5FFFD7, 0x5FFFFF,\n    0x870000, 0x87005F, 0x870087, 0x8700AF, 0x8700D7, 0x8700FF, 0x875F00, 0x875F5F,\n    0x875F87, 0x875FAF, 0x875FD7, 0x875FFF, 0x878700, 0x87875F, 0x878787, 0x8787AF,\n    0x8787D7, 0x8787FF, 0x87AF00, 0x87AF5F, 0x87AF87, 0x87AFAF, 0x87AFD7, 0x87AFFF,\n    0x87D700, 0x87D75F, 0x87D787, 0x87D7AF, 0x87D7D7, 0x87D7FF, 0x87FF00, 0x87FF5F,\n    0x87FF87, 0x87FFAF, 0x87FFD7, 0x87FFFF, 0xAF0000, 0xAF005F, 0xAF0087, 0xAF00AF,\n    0xAF00D7, 0xAF00FF, 0xAF5F00, 0xAF5F5F, 0xAF5F87, 0xAF5FAF, 0xAF5FD7, 0xAF5FFF,\n    0xAF8700, 0xAF875F, 0xAF8787, 0xAF87AF, 0xAF87D7, 0xAF87FF, 0xAFAF00, 0xAFAF5F,\n    0xAFAF87, 0xAFAFAF, 0xAFAFD7, 0xAFAFFF, 0xAFD700, 0xAFD75F, 0xAFD787, 0xAFD7AF,\n    0xAFD7D7, 0xAFD7FF, 0xAFFF00, 0xAFFF5F, 0xAFFF87, 0xAFFFAF, 0xAFFFD7, 0xAFFFFF,\n    0xD70000, 0xD7005F, 0xD70087, 0xD700AF, 0xD700D7, 0xD700FF, 0xD75F00, 0xD75F5F,\n    0xD75F87, 0xD75FAF, 0xD75FD7, 0xD75FFF, 0xD78700, 0xD7875F, 0xD78787, 0xD787AF,\n    0xD787D7, 0xD787FF, 0xD7AF00, 0xD7AF5F, 0xD7AF87, 0xD7AFAF, 0xD7AFD7, 0xD7AFFF,\n    0xD7D700, 0xD7D75F, 0xD7D787, 0xD7D7AF, 0xD7D7D7, 0xD7D7FF, 0xD7FF00, 0xD7FF5F,\n    0xD7FF87, 0xD7FFAF, 0xD7FFD7, 0xD7FFFF, 0xFF0000, 0xFF005F, 0xFF0087, 0xFF00AF,\n    0xFF00D7, 0xFF00FF, 0xFF5F00, 0xFF5F5F, 0xFF5F87, 0xFF5FAF, 0xFF5FD7, 0xFF5FFF,\n    0xFF8700, 0xFF875F, 0xFF8787, 0xFF87AF, 0xFF87D7, 0xFF87FF, 0xFFAF00, 0xFFAF5F,\n    0xFFAF87, 0xFFAFAF, 0xFFAFD7, 0xFFAFFF, 0xFFD700, 0xFFD75F, 0xFFD787, 0xFFD7AF,\n    0xFFD7D7, 0xFFD7FF, 0xFFFF00, 0xFFFF5F, 0xFFFF87, 0xFFFFAF, 0xFFFFD7, 0xFFFFFF,\n    0x080808, 0x121212, 0x1C1C1C, 0x262626, 0x303030, 0x3A3A3A, 0x444444, 0x4E4E4E,\n    0x585858, 0x626262, 0x6C6C6C, 0x767676, 0x808080, 0x8A8A8A, 0x949494, 0x9E9E9E,\n    0xA8A8A8, 0xB2B2B2, 0xBCBCBC, 0xC6C6C6, 0xD0D0D0, 0xDADADA, 0xE4E4E4, 0xEEEEEE \n};\n"
  },
  {
    "path": "kernel/fonts/piccolo_7x6.c",
    "content": "const unsigned long font_height = 7;\nconst unsigned long font_width  = 6;\nconst unsigned char fb_font[256][7] = {\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20},\n    {0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00},\n    {0x50, 0x50, 0xf8, 0x50, 0xf8, 0x50, 0x50},\n    {0x20, 0x78, 0xa0, 0x70, 0x28, 0xf0, 0x20},\n    {0xc0, 0xc8, 0x10, 0x20, 0x40, 0x98, 0x18},\n    {0x40, 0xa0, 0xa0, 0x40, 0xa8, 0x90, 0x68},\n    {0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00},\n    {0x20, 0x40, 0x80, 0x80, 0x80, 0x40, 0x20},\n    {0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20},\n    {0x20, 0xa8, 0x70, 0x20, 0x70, 0xa8, 0x20},\n    {0x00, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40},\n    {0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},\n    {0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00},\n    {0x70, 0x88, 0x98, 0xa8, 0xc8, 0x88, 0x70},\n    {0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70},\n    {0x70, 0x88, 0x08, 0x30, 0x40, 0x80, 0xf8},\n    {0xf8, 0x08, 0x10, 0x30, 0x08, 0x88, 0x70},\n    {0x10, 0x30, 0x50, 0x90, 0xf8, 0x10, 0x10},\n    {0xf8, 0x80, 0xf0, 0x08, 0x08, 0x88, 0x70},\n    {0x38, 0x40, 0x80, 0xf0, 0x88, 0x88, 0x70},\n    {0xf8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40},\n    {0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70},\n    {0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0xe0},\n    {0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00},\n    {0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x40},\n    {0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10},\n    {0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00},\n    {0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40},\n    {0x70, 0x88, 0x10, 0x20, 0x20, 0x00, 0x20},\n    {0x70, 0x88, 0xa8, 0xb8, 0xb0, 0x80, 0x78},\n    {0x20, 0x50, 0x88, 0x88, 0xf8, 0x88, 0x88},\n    {0xf0, 0x88, 0x88, 0xf0, 0x88, 0x88, 0xf0},\n    {0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70},\n    {0xf0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xf0},\n    {0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0xf8},\n    {0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80},\n    {0x78, 0x80, 0x80, 0x80, 0x98, 0x88, 0x78},\n    {0x88, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x88},\n    {0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70},\n    {0x08, 0x08, 0x08, 0x08, 0x08, 0x88, 0x70},\n    {0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88},\n    {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8},\n    {0x88, 0xd8, 0xa8, 0xa8, 0x88, 0x88, 0x88},\n    {0x88, 0x88, 0xc8, 0xa8, 0x98, 0x88, 0x88},\n    {0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70},\n    {0xf0, 0x88, 0x88, 0xf0, 0x80, 0x80, 0x80},\n    {0x70, 0x88, 0x88, 0x88, 0xa8, 0x90, 0x68},\n    {0xf0, 0x88, 0x88, 0xf0, 0xa0, 0x90, 0x88},\n    {0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70},\n    {0xf8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20},\n    {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70},\n    {0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20},\n    {0x88, 0x88, 0x88, 0xa8, 0xa8, 0xd8, 0x88},\n    {0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88},\n    {0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20},\n    {0xf8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xf8},\n    {0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf8},\n    {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00},\n    {0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8},\n    {0x00, 0x00, 0x20, 0x50, 0x88, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8},\n    {0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x68, 0x98, 0x88, 0x98, 0x68},\n    {0x80, 0x80, 0xb0, 0xc8, 0x88, 0xc8, 0xb0},\n    {0x00, 0x00, 0x38, 0x40, 0x40, 0x40, 0x38},\n    {0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68},\n    {0x00, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x70},\n    {0x10, 0x20, 0x20, 0x70, 0x20, 0x20, 0x20},\n    {0x00, 0x00, 0x68, 0x98, 0x88, 0x78, 0x08},\n    {0x80, 0x80, 0xf0, 0x88, 0x88, 0x88, 0x88},\n    {0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70},\n    {0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10},\n    {0x80, 0x80, 0x90, 0xa0, 0xe0, 0x90, 0x88},\n    {0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70},\n    {0x00, 0x00, 0xd8, 0xa4, 0xa4, 0xa4, 0xa4},\n    {0x00, 0x00, 0xf0, 0x88, 0x88, 0x88, 0x88},\n    {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70},\n    {0x00, 0x00, 0xb0, 0xc8, 0x88, 0xc8, 0xb0},\n    {0x00, 0x00, 0x68, 0x98, 0x88, 0x98, 0x68},\n    {0x00, 0x00, 0xb0, 0xc0, 0x80, 0x80, 0x80},\n    {0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xf0},\n    {0x20, 0x20, 0xf8, 0x20, 0x20, 0x20, 0x20},\n    {0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x78},\n    {0x00, 0x00, 0x88, 0x88, 0x50, 0x50, 0x20},\n    {0x00, 0x00, 0xa4, 0xa4, 0xa4, 0xa4, 0x58},\n    {0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88},\n    {0x00, 0x00, 0x48, 0x48, 0x48, 0x78, 0x08},\n    {0x00, 0x00, 0xf8, 0x10, 0x20, 0x40, 0xf8},\n    {0x18, 0x20, 0x20, 0x40, 0x20, 0x20, 0x18},\n    {0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20},\n    {0xc0, 0x20, 0x20, 0x10, 0x20, 0x20, 0xc0},\n    {0x00, 0x00, 0x08, 0x70, 0x80, 0x00, 0x00},\n    {0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\n};\n"
  },
  {
    "path": "kernel/fortuna.h",
    "content": "#ifndef FORTUNA_H_\n#define FORTUNA_H_\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n/* Defines for hash and encryption algorithms */\n#define FORTUNA_HASH_SIZE             32\n#define FORTUNA_ENCRYPT_IV_SIZE       16\n#define FORTUNA_ENCRYPT_KEY_SIZE      32\n#define FORTUNA_ENCRYPT_BLOCK_SIZE    16\n\nint fortuna_init(void);\nvoid fortuna_accu(int source, int pool, uint8_t *data, int data_size);\n\n/* Get random stuff! */\nint fortuna_get_bytes(uint8_t *buffer, int count);\n\n/* Shut down the generator securely if it is no longer needed */\nvoid fortuna_shutdown(void);\n\n#endif /* FORTUNA_H_ */\n\n"
  },
  {
    "path": "kernel/fpb.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n */\n\n\n#include \"fpb.h\"\n#include <libopencmsis/core_cm3.h>\n\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n#define FPB_NUM_CODE2_OFF   12\n#define FPB_NUM_LIT_MASK_OFF 8\n#define FPB_NUM_CODE1_OFF    4\n\n\n#define DBG_DHCSR MMIO32(0xE000EDF0)\n#define DBG_DEMCR MMIO32(0xE000EDFC)\n\n#define DBG_DHCSR_KEY ((0xA0 << 24) | (0x5F << 16))\n#define DBG_DHCSR_HALT (1 << 1)\n#define DBG_DHCSR_STEP (1 << 2)\n\n\n#define DBG_DEMCR_MON_STEP (1 << 18)\n#define DBG_DEMCR_MON_PEND (1 << 17)\n#define DBG_DEMCR_MON_EN (1 << 16)\n\n#define FPB_REPLACE_LO (1 << 30)\n#define FPB_REPLACE_HI (2 << 30)\n#define FPB_REPLACE_BOTH (3 << 30)\n\n\nstruct bkpt {\n    int pid;\n    void *b;\n};\n\nstruct bkpt bkpt[8];\n\nvoid debug_monitor_handler(void)\n{\n    int pid;\n    kprintf(\"TRAP!\\r\\n\");\n    /* Exit debug state */\n    task_hit_breakpoint(this_task());\n    DBG_DHCSR = DBG_DHCSR_KEY;\n}\n\nint fpb_setbrk(int pid, void *bpoint, int n)\n{\n    int i;\n    if (n < 0) {\n        for (i = 0; i < 8; i++) {\n            if (bkpt[i].pid == 0) {\n                n = i;\n                break;\n            }\n        }\n    }\n    if (n < 0)\n        return -1;\n    bkpt[n].pid = pid;\n    bkpt[n].b = bpoint;\n    if ((uint32_t)bpoint & 0x01)\n        return -1;\n    if ((uint32_t)bpoint & 0x02)\n        FPB_COMP[n] = FPB_COMP_ENABLE | (((uint32_t)bpoint) & (0x1FFFFFFC)) | FPB_REPLACE_HI;\n    else\n        FPB_COMP[n] = FPB_COMP_ENABLE | (((uint32_t)bpoint) & (0x1FFFFFFC)) | FPB_REPLACE_LO;\n    return n;\n}\n\nint fpb_delbrk(int n)\n{\n    bkpt[n].pid = 0;\n    FPB_COMP[n] = 0;\n}\n\n\nint fpb_init(void)\n{\n    if (FPB_CTRL == 0x0) {\n        return -1;\n    }\n    if (FPB_COMP[0] == 0x0) {\n        return -1;\n    }\n    /* Enable Debug Monitor Exception */\n    DBG_DEMCR = DBG_DEMCR_MON_EN;\n    FPB_CTRL = FPB_CTRL_ENABLE | FPB_CTRL_KEY | (1 << FPB_NUM_CODE2_OFF) | (2 << FPB_NUM_LIT_MASK_OFF);\n    nvic_enable_irq(DEBUG_MONITOR_IRQ);\n}\n\n#endif\n"
  },
  {
    "path": "kernel/fpb.h",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n */\n\n#ifndef FROSTED_FPB_INC\n#define FROSTED_FPB_INC\n\n#include \"frosted.h\"\n/* Those defined only on ARMv7 and above */\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n#include <cm3/fpb.h>\n\nint fpb_init(void);\nint fpb_setbrk(int pid, void *bpoint, int n);\nint fpb_delbrk(int n);\n\n#endif\n#endif\n"
  },
  {
    "path": "kernel/framebuffer.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n \n#include \"frosted.h\"\n#include \"device.h\"\n#include \"framebuffer.h\"\n#include <stdint.h>\n#include <sys/ioctl.h>\n\n#ifdef STM32F7\n#   include \"unicore-mx/stm32/ltdc.h\"\n#endif\n\n\n#define MAX_FBS         (1)\n\n\nstatic struct fb_info *fb[MAX_FBS] = { 0 };\n\nstatic int fb_write(struct fnode *fno, const void *buf, unsigned int len);\nstatic int fb_read(struct fnode *fno, void *buf, unsigned int len);\nstatic int fb_open(const char *path, int flags);\nstatic int fb_seek(struct fnode *fno, int off, int whence);\nstatic int fb_ioctl(struct fnode * fno, const uint32_t cmd, void *arg);\n\nstatic struct module mod_devfb = {\n    .family = FAMILY_FILE,\n    .name = \"framebuffer\",\n    .ops.open = fb_open,\n    .ops.read = fb_read,\n    .ops.write = fb_write,\n    .ops.seek = fb_seek,\n    .ops.ioctl = fb_ioctl,\n};\n\n\nstatic int fb_open(const char *path, int flags)\n{\n    struct fnode *f = fno_search(path);\n    if (!f)\n        return -1;\n    return device_open(path, flags);\n}\n\nstatic int fb_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    int len_left;\n    struct fb_info *fb;\n    uint32_t off;\n\n    if (len == 0)\n        return len;\n\n    fb = (struct fb_info *)FNO_MOD_PRIV(fno, &mod_devfb);\n    if (!fb)\n        return -1;\n\n    //mutex_lock(fb->dev->mutex);\n    off = task_fd_get_off(fno);\n    len_left = fno->size - off;\n    if (len > len_left)\n        len = len_left;\n\n    if (!len)\n        return 0;\n\n    /* write to framebuffer memory */\n    memcpy((void *)((uint8_t *)fb->screen_buffer + off) , buf, len); \n    off += len;\n    task_fd_set_off(fno, off);\n\n    //mutex_unlock(fb->dev->mutex);\n    return len;\n}\n\n\nstatic int fb_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    int len_left;\n    struct fb_info *fb;\n    uint32_t off;\n    off = task_fd_get_off(fno);\n\n    if (len == 0)\n        return len;\n\n    len_left = fno->size - off;\n    if (len > len_left)\n        len = len_left;\n\n    if (!len)\n        return 0;\n\n    fb = (struct fb_info *)FNO_MOD_PRIV(fno, &mod_devfb);\n    if (!fb)\n        return -1;\n\n    // mutex_lock(fb->dev->mutex);\n\n    //XXX: max len = MAX_FB_SIZE;\n    memcpy(buf, (void *)((uint8_t *)fb->screen_buffer + off), len);\n    off += len;\n    task_fd_set_off(fno, off);\n\n    //mutex_unlock(fb->dev->mutex);\n    return len;\n}\n\nstatic int fb_seek(struct fnode *fno, int off, int whence)\n{\n    struct fb_info *fb;\n    int new_off;\n\n    switch(whence) {\n        case SEEK_CUR:\n            new_off = task_fd_get_off(fno) + off;\n            break;\n        case SEEK_SET:\n            new_off = off;\n            break;\n        case SEEK_END:\n            new_off = fno->size + off;\n            break;\n        default:\n            return -1;\n    }\n\n    if (new_off < 0)\n        new_off = 0;\n\n    if (new_off > fno->size) {\n        return -1;\n    }\n    task_fd_set_off(fno, new_off);\n    return new_off;\n}\n\nstatic int fb_fno_init(struct fnode *dev, struct fb_info * fb)\n{\n    static int num_fb = 0;\n    char name[4] = \"fb\";\n\n    if (!fb)\n        return -1;\n\n    name[2] =  '0' + num_fb++;\n    fb->dev = device_fno_init(&mod_devfb, name, dev, FL_TTY, fb);\n    fb->dev->fno->size = fb->var.yres * fb->var.xres * fb->var.bits_per_pixel;\n    return 0;\n}\n\nstatic int fb_ioctl(struct fnode * fno, const uint32_t cmd, void *arg)\n{\n    struct fb_info * fb = (struct fb_info *)FNO_MOD_PRIV(fno, &mod_devfb);\n    if (!fb)\n        return -1;\n\n    (void)arg;\n    if (cmd == IOCTL_FB_GETCMAP) {\n        return 0;\n    }\n    if (cmd == IOCTL_FB_PUTCMAP) {\n        return fb->fbops->fb_setcmap((uint32_t *)arg, fb);\n    }\n    if (cmd == IOCTL_FB_GET_FSCREENINFO) {\n        struct fb_fix_screeninfo *fbi = (struct fb_fix_screeninfo *)arg;\n        if (!arg)\n            return -1;\n        memcpy(arg, &fb->var, sizeof(struct fb_fix_screeninfo));\n        return 0;\n    }\n    return -1;\n}\n\nunsigned char *framebuffer_get(void)\n{\n    return fb[0]->screen_buffer;\n}\n\nint framebuffer_setcmap(uint32_t *ptr)\n{\n    return fb[0]->fbops->fb_setcmap(ptr, fb[0]);\n}\n\n/* Register a low-level framebuffer driver */\nint register_framebuffer(struct fb_info *fb_info)\n{\n    struct fnode *devfs = fno_search(\"/dev\");\n    if (!fb_info)\n        return -1;\n\n    /* Ony one FB supported for now */\n    fb_fno_init(devfs, fb_info);\n    \n    if (!fb_info->fbops)\n        return -1;\n\n    if (fb_info->fbops->fb_open)\n        fb_info->fbops->fb_open(fb_info);\n\n    if (fb_info->fbops->fb_blank)\n        fb_info->fbops->fb_blank(fb_info);\n\n    fb[0] = fb_info;\n\n    register_module(&mod_devfb);\n\n    return 0;\n}\n"
  },
  {
    "path": "kernel/frand.h",
    "content": "#ifndef FRAND_H_\n#define FRAND_H_\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"frosted.h\"\n\nstruct frand_ops;\n\nstruct frand_info {\n        struct frand_ops *frandops;\n        struct device *dev;             /* This is this frand device */\n};\n\nstruct frand_ops {\n        /* open/release and usage marking */\n        int (*frand_open)(struct frand_info *info);\n};\n\n/* For setting up the generator and feeding entropy */\n/* low-level drivers must call this register function first */\nint register_frand(struct frand_info *frand_info);\n\n/* kernel init */\nvoid frand_init(struct fnode *dev);\n\n#endif /* FRAND_H_ */\n\n"
  },
  {
    "path": "kernel/frosted.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include <sys/vfs.h>\n#include \"kprintf.h\"\n#include \"bflt.h\"\n#include \"null.h\"\n#include \"xipfs.h\"\n#include \"vfs.h\"\n#include \"gpio.h\"\n#include \"uart.h\"\n#include \"rng.h\"\n#include \"sdram.h\"\n#include \"socket_in.h\"\n#include \"fatfs.h\"\n#include \"framebuffer.h\"\n#include \"ltdc.h\"\n#include \"fbcon.h\"\n#include \"usb.h\"\n#include \"eth.h\"\n#include \"exti.h\"\n#include \"pty.h\"\n#include \"lowpower.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include \"libopencmsis/core_cm3.h\"\n#include \"tty_console.h\"\n\n#ifdef CONFIG_PICOTCP\n# include \"pico_stack.h\"\n#endif\n\n#ifdef CONFIG_PICOTCP_LOOP\nstruct pico_device *pico_loop_create(void);\n#else\n# define pico_loop_create() NULL\n#endif\n\n#define IDLE() while(1){do{}while(0);}\n\nstatic int tcpip_timer_pending = 0;\n\n/* The following needs to be defined by\n * the application code\n */\nvoid (*init)(void *arg) = (void (*)(void*))(FLASH_ORIGIN + APPS_ORIGIN);\n\nvoid simple_hard_fault_handler(void)\n{\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    volatile uint32_t hfsr = SCB_HFSR;\n    //volatile uint32_t bfsr = SCB_BFSR;\n    volatile uint32_t afsr = SCB_AFSR;\n    volatile uint32_t bfar = SCB_BFAR;\n    //volatile uint32_t ufsr = SCB_UFSR;\n    volatile uint32_t mmfar = SCB_MMFAR;\n#endif\n    while(1);\n}\n\n#ifdef CONFIG_HARDFAULT_DBG\n\nvolatile unsigned long stacked_r0 ;\nvolatile unsigned long stacked_r1 ;\nvolatile unsigned long stacked_r2 ;\nvolatile unsigned long stacked_r3 ;\nvolatile unsigned long stacked_r12 ;\nvolatile unsigned long stacked_lr ;\nvolatile unsigned long stacked_pc ;\nvolatile unsigned long stacked_psr ;\nvolatile unsigned long _CFSR ;\nvolatile unsigned long _HFSR ;\nvolatile unsigned long _DFSR ;\nvolatile unsigned long _AFSR ;\nvolatile unsigned long _BFAR ;\nvolatile unsigned long _MMAR ;\n\nvoid hardfault_handler_dbg(unsigned long *hardfault_args){\n    stacked_r0 = ((unsigned long)hardfault_args[0]) ;\n    stacked_r1 = ((unsigned long)hardfault_args[1]) ;\n    stacked_r2 = ((unsigned long)hardfault_args[2]) ;\n    stacked_r3 = ((unsigned long)hardfault_args[3]) ;\n    stacked_r12 = ((unsigned long)hardfault_args[4]) ;\n    stacked_lr = ((unsigned long)hardfault_args[5]) ;\n    stacked_pc = ((unsigned long)hardfault_args[6]) ;\n    stacked_psr = ((unsigned long)hardfault_args[7]) ;\n\n    // Configurable Fault Status Register\n    // Consists of MMSR, BFSR and UFSR\n    _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ;\n\n\n\n    // Hard Fault Status Register\n    _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ;\n\n    // Debug Fault Status Register\n    _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ;\n\n    // Auxiliary Fault Status Register\n    _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ;\n\n    // Read the Fault Address Registers. These may not contain valid values.\n    // Check BFARVALID/MMARVALID to see if they are valid values\n    // MemManage Fault Address Register\n    _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ;\n    // Bus Fault Address Register\n    _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ;\n    __asm(\"BKPT #0\") ; // Break into the debugger\n}\n#else\nvoid hardfault_handler_dbg(unsigned long *sp)\n{\n    __asm(\"BKPT #0\") ; // Break into the debugger\n}\n\n#endif\n\n\n__attribute__((naked)) void hard_fault_handler(void)\n{\n    __asm(\"MOVS R0, #4          \\n\"\n          \"MOVS R1, LR          \\n\"\n          \"TST R0, R1           \\n\"\n          \"BEQ _MSP             \\n\"\n          \"MRS R0, PSP          \\n\"\n          \"B hardfault_handler_dbg \\n\"\n      \"_MSP:\"\n          \"MRS R0, MSP          \\n\"\n          \"B hardfault_handler_dbg \\n\"\n           );\n}\n\nvoid mem_manage_handler(void)\n{\n#   define ARM_CFSR (*(volatile uint32_t *)(0xE000ED28))\n#   define ARM_MMFAR (*(volatile uint32_t *)(0xE000ED34))\n    volatile uint32_t address = 0xFFFFFFFF;\n    volatile uint32_t instruction = 0xFFFFFFFF;\n    uint32_t *top_stack;\n\n    if ((ARM_CFSR & 0x80)!= 0) {\n        address = ARM_MMFAR;\n        asm volatile (\"mrs %0, psp\" : \"=r\" (top_stack));\n        instruction = *(top_stack - 1);\n    }\n\n    if (task_segfault(address, instruction, MEMFAULT_ACCESS) < 0)\n        while(1);\n}\n\nvoid bus_fault_handler(void)\n{\n    while(1);\n}\n\nvoid usage_fault_handler(void)\n{\n    while(1);\n}\n\nstatic void hw_init(void)\n{\n    gpio_init();\n    exti_init();\n    uart_init();\n    ptmx_init();\n    rng_init();\n    sdram_init();\n    machine_init();\n    lowpower_init();\n    SysTick_Config(CONFIG_SYS_CLOCK / 1000);\n}\n\nint frosted_init(void)\n{\n    extern void * _k__syscall__;\n    int xip_mounted;\n    /* ktimers must be enabled before systick */\n    ktimer_init();\n\n    kernel_task_init();\n\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    fpb_init();\n#endif\n\n    vfs_init();\n    devnull_init(fno_search(\"/dev\"));\n\n    /* Set up system */\n\n\n    hw_init();\n    mpu_init();\n\n    syscalls_init();\n\n    memfs_init();\n    xipfs_init();\n    sysfs_init();\n    fatfs_init();\n\n    ltdc_init();\n    fbcon_init( 480, 272);\n    tty_console_init();\n\n    vfs_mount(NULL, \"/tmp\", \"memfs\", 0, NULL);\n    xip_mounted = vfs_mount((char *)init, \"/bin\", \"xipfs\", 0, NULL);\n    vfs_mount(NULL, \"/sys\", \"sysfs\", 0, NULL);\n\n    klog_init();\n\n\n#ifdef UNIX\n    socket_un_init();\n#endif\n\n    return xip_mounted;\n}\n\nstatic void ktimer_tcpip(uint32_t time, void *arg);\n\n#ifdef CONFIG_PICOTCP\nvoid frosted_tcpip_wakeup(void)\n{\n}\n#endif\n\n\nstatic const char init_path[] = \"/bin/init\";\nstatic const char *const init_args[2] = { init_path, NULL };\n\n#ifdef CONFIG_USBHOST\nstruct usbh_host *USBHost = NULL;\n#endif\n\nvoid frosted_kernel(int xipfs_mounted)\n{\n    struct vfs_info *vfsi = NULL;\n\n    if (xipfs_mounted == 0)\n    {\n        struct fnode *fno = fno_search(init_path);\n        void * memptr;\n        size_t mem_size;\n        size_t stack_size;\n        uint32_t got_loc;\n        if (!fno) {\n            /* PANIC: Unable to find /bin/init */\n            while(1 < 2);\n        }\n\n        if (fno->owner && fno->owner->ops.exe) {\n            vfsi = fno->owner->ops.exe(fno, (void *)init_args);\n            task_create(vfsi, (void *)init_args, NICE_DEFAULT);\n        }\n    } else {\n        IDLE();\n    }\n\n\n#ifdef CONFIG_PICOTCP\n    pico_stack_init();\n    socket_in_init();\n    pico_lock_init();\n\n    /* Network devices initialization */\n    usb_ethernet_init(USB_DEV_FS);\n    pico_loop_create();\n    pico_eth_start();\n#endif\n\n    frosted_scheduler_on();\n\n    while(1) {\n        check_tasklets();\n#ifdef CONFIG_PICOTCP\n        if (pico_trylock_kernel() == 0) {\n            pico_stack_tick();\n            pico_unlock();\n        }\n#endif\n        asm volatile (\"wfe\");\n        //__WFI();\n    }\n}\n\n/* OS entry point */\nvoid main(void)\n{\n    int xipfs_mounted;\n    xipfs_mounted = frosted_init();\n    frosted_kernel(xipfs_mounted); /* never returns */\n}\n\n"
  },
  {
    "path": "kernel/frosted.h",
    "content": "#ifndef FROSTED_INCLUDED_H\n#define FROSTED_INCLUDED_H\n\n#define KERNEL\n#include \"frosted_api.h\"\n#include \"malloc.h\"\n#include \"interrupts.h\"\n#include \"string.h\"\n#include \"errno.h\"\n#include \"vfs.h\"\n#include \"kprintf.h\"\n#include \"mpu.h\"\n\n#define TASK_IDLE       0\n#define TASK_RUNNABLE   1\n#define TASK_RUNNING    2\n#define TASK_WAITING    3\n#define TASK_FORKED     4\n#define TASK_STOPPED    5\n#define TASK_ZOMBIE     0x66\n#define TASK_OVER       0xFF\n\n#define MEMFAULT_ACCESS 0x00\n#define MEMFAULT_DOUBLEFREE 0x01\n\n//#define DEBUG\n\n#include <stdint.h>\n#include <string.h>\n#include <sys/time.h>\n\n\n/* Types */\nstruct task;\nstruct fnode;\nstruct semaphore;\nstruct termios;\ntypedef struct semaphore sem_t;\ntypedef struct semaphore mutex_t;\n\ntypedef uint32_t sigset_t;\n\n/* generics */\nvolatile unsigned int jiffies;\nvolatile unsigned int rt_offset;\nvolatile int _syscall_retval;\n\n/* Mach-specific initialization */\nint machine_init(void);\n\n/* Systick & co. */\nint _clock_interval;\nvoid SysTick_Hook(void);\nint SysTick_Interval(unsigned long interval);\nvoid SysTick_on(void);\nvoid SysTick_off(void);\nint SysTick_interval(unsigned long interval);\nvoid ktimer_init(void);\nint fpb_init(void);\n\nstruct ktimer;\nint ktimer_add(uint32_t count, void (*handler)(uint32_t, void *), void *arg);\nint ktimer_del(int tid);\nvoid ktimer_cancel(struct ktimer *t);\n\n/* FS initializers */\nvoid memfs_init(void);\nstruct sysfs_fnode {\n    struct fnode *fnode;\n    int (*do_read)(struct sysfs_fnode *sfs, void *buf, int len);\n    int (*do_write)(struct sysfs_fnode *sfs, const void *buf, int len);\n};\nvoid sysfs_init(void);\n\n\n/* Scheduler */\n#define NICE_DEFAULT (0)\n#define NICE_RT (0 - 20)\n#define NICE_MAX (20)\n\n/* Called by boot code.\n * Set system NVIC priorities and start systick. */\nvoid frosted_scheduler_on(void);\n\n/* Forced preemption */\nvoid task_preempt(void);\nvoid task_preempt_all(void);\n\n/* Execute/terminate a process. */\nint scheduler_exec(struct vfs_info *v, void *args);\nint task_create(struct vfs_info *vfsi, void *arg, unsigned int prio);\nint task_kill(int pid, int signal);\n\n/* Getter functions. XXX refactor to thread id XXX */\nchar * scheduler_task_name(int pid);\nint scheduler_task_state(int pid);\nunsigned scheduler_stack_used(int pid);\nint scheduler_get_nice(int pid);\n\n/* Get the task object for the current task */\nstruct task *this_task(void);\nuint16_t this_task_getpid(void);\n\n/* Resume target task */\nvoid task_resume(struct task *t);\nvoid task_resume_lock(struct task *t);\nvoid task_wakeup(struct task *t);\n\n/* Called by FPB when a task hits a breakpoint */\nvoid task_hit_breakpoint(struct task *t);\n\n\n/* Functions targeting the Current (Running) task\n * */\nint task_in_syscall(void);\nint task_running(void);\nint task_filedesc_add(struct fnode *f);\nint task_fd_setmask(int fd, uint32_t mask);\nuint32_t task_fd_getmask(int fd);\nuint32_t task_fd_set_flags(int fd, uint32_t flags);\nuint32_t task_fd_get_flags(int fd);\nuint32_t task_fd_set_off(struct fnode *fno, uint32_t off);\nuint32_t task_fd_get_off(struct fnode *fno);\nstruct fnode *task_filedesc_get(int fd);\nint task_segfault(uint32_t addr, uint32_t instr, int flags);\nint task_fd_readable(int fd);\nint task_fd_writable(int fd);\nint task_filedesc_del(int fd);\nvoid task_suspend(void);\n/* Validate userspace pointers passed in the syscalls. */\nint task_ptr_valid(const void *ptr);\n/* Slice off one unit from the task current run time */\nint task_timeslice(void);\nstruct fnode *task_getcwd(void);\nvoid task_chdir(struct fnode *f);\n\n/* Naming is not nice, implications of renaming is refactoring */\nvoid sleepy_task_wakeup(uint32_t now, void *arg);\n\n/* Manage timer IDs */\nint task_get_timer_id(void);\nvoid task_set_timer_id(int id);\n\n/* Semaphores */\nint sem_wait(sem_t *s, struct timespec *t);\nint sem_trywait(sem_t *s);\nint sem_post(sem_t *s);\nint sem_init(sem_t *s, int val);\nint sem_destroy(sem_t *s);\n\n/* Mutexen */\nint mutex_lock(mutex_t *s);\nint mutex_trylock(mutex_t *s);\nint mutex_unlock(mutex_t *s);\nmutex_t *mutex_init();\nvoid mutex_destroy(mutex_t *s);\n\n#define schedule()   *((uint32_t volatile *)0xE000ED04) = 0x10000000\n\n/* Timers */\nint Timer_on(unsigned int n);\n\n/* Tasklets */\nvoid tasklet_add(void (*exe)(void*), void *arg);\nvoid check_tasklets(void);\n\n/* Kthreads */\nstruct task *kthread_create(void (routine)(void *), void *arg);\nvoid kthread_sleep_ms(uint32_t ms);\nvoid task_yield(void);\nvoid kthread_yield(void);\nint kthread_cancel(struct task *t);\n\n/* Modules */\nstruct module *MODS;\nint register_module(struct module *m);\nint unregister_module(struct module *m);\nstruct module *module_search(char *name);\n\n/* System */\nint sys_register_handler(uint32_t n, int (*_sys_c)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t));\nint syscall(uint32_t syscall_nr, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5);\nvoid syscalls_init(void);\nint task_is_interrupted(void);\n\n#define SYS_CALL_AGAIN_VAL (-1024)\n//#define SYS_CALL_AGAIN (task_is_interrupted()?(-EINTR):(SYS_CALL_AGAIN_VAL))\n#define SYS_CALL_AGAIN SYS_CALL_AGAIN_VAL\n\n/* VFS */\nvoid vfs_init(void);\nint fno_fullpath(struct fnode *f, char *dst, int len);\nvoid fno_use(struct fnode *f);\n\n#define FL_RDONLY 0x01\n#define FL_WRONLY 0x02\n#define FL_RDWR   (FL_RDONLY | FL_WRONLY)\n#define FL_DIR    0x04\n#define FL_INUSE  0x08\n#define FL_TTY    0x10\n#define FL_BLK    0x20\n\n#define FL_EXEC   0x40\n#define FL_LINK   0x80\n\n#ifndef FD_CLOEXEC\n    #define FD_CLOEXEC\t1\n#endif\n\n#ifndef F_DUPFD\n    #define F_DUPFD 0\n#endif\n\n#ifndef F_GETFD\n    #define F_GETFD 1\n#endif\n\n#ifndef F_SETFD\n    #define F_SETFD 2\n#endif\n\n#ifndef F_GETFL\n    #define F_GETFL 3\n#endif\n\n#ifndef F_SETFL\n    #define F_SETFL 4\n#endif\n\n\nstruct fnode {\n    struct module *owner;\n    char *fname;\n    char *linkname;\n    uint32_t flags;\n    struct fnode *parent;\n    struct fnode *children;\n    void *priv;\n    uint32_t dir_ptr;\n    uint32_t size;\n    int32_t usage_count;\n    struct fnode *next;\n};\n\n#define FNO_MOD_PRIV(fno,mod) (((fno == NULL)?NULL:((mod != fno->owner)?NULL:(fno->priv))))\n#define FNO_BLOCKING(f) ((f->flags & O_NONBLOCK) == 0)\n\nstruct mountpoint\n{\n    struct fnode *target;\n    struct mountpoint *next;\n};\n\nstruct fnode *fno_create(struct module *owner, const char *name, struct fnode *parent);\nstruct fnode *fno_create_rdonly(struct module *owner, const char *name, struct fnode *parent);\nstruct fnode *fno_create_wronly(struct module *owner, const char *name, struct fnode *parent);\nstruct fnode *fno_mkdir(struct module *owner, const char *name, struct fnode *parent);\nvoid fno_unlink(struct fnode *fno);\nstruct fnode *fno_search(const char *path);\nint vfs_symlink(char *file, char *link);\n\n/* Modules (for files/sockets) */\nint register_addr_family(struct module *m, uint16_t family);\n\n\n#define FAMILY_UNIX 0x0001\n#define FAMILY_INET 0x0002\n#define FAMILY_DEV  0x0DEF\n#define FAMILY_FILE 0xFFFF\n\n#define MODNAME_SIZE 32\n\n\nstruct module {\n    uint16_t family;\n    char name[MODNAME_SIZE];\n\n    /* If this is a filesystem related module, it should probably define these */\n    int (*mount)(char *source, char *target, uint32_t flags, void *arg);\n    int (*umount)(char *target, uint32_t flags);\n    int (*mount_info)(struct fnode *fno, char *buf, int size);\n\n    struct module_operations {\n        /* Common module operations */\n        int (*read) (struct fnode *fno, void *buf, unsigned int len);\n        int (*write)(struct fnode *fno, const void *buf, unsigned int len);\n        int (*poll) (struct fnode *fno, uint16_t events, uint16_t *revents);\n        int (*close)(struct fnode *fno);\n        int (*ioctl)(struct fnode *fno, const uint32_t cmd, void *arg);\n\n        /* Files only (NULL == socket) */\n        int (*open)(const char *path, int flags);\n        int (*seek)(struct fnode *fno, int offset, int whence);\n        int (*creat)(struct fnode *fno);\n        int (*unlink)(struct fnode *fno);\n        int (*truncate)(struct fnode *fno, unsigned int size);\n        void * (*exe)(struct fnode *fno, void *arg);\n\n        /* Sockets only (NULL == file) */\n        int (*socket)(int domain, int type, int protocol);\n        int (*recvfrom)(int fd, void *buf, unsigned int len, int flags, struct sockaddr *addr, unsigned int *addrlen);\n        int (*sendto)(int fd, const void *buf, unsigned int len, int flags, struct sockaddr *addr, unsigned int addrlen);\n        int (*bind)(int fd, struct sockaddr *addr, unsigned int addrlen);\n        int (*accept)(int fd, struct sockaddr *addr, unsigned int *addrlen);\n        int (*connect)(int fd, struct sockaddr *addr, unsigned int addrlen);\n        int (*listen)(int fd, int backlog);\n        int (*shutdown)(int fd, uint16_t how);\n        int (*setsockopt)(int sd, int level, int optname, void *optval, unsigned int optlen);\n        int (*getsockopt)(int sd, int level, int optname, void *optval, unsigned int *optlen);\n        int (*getsockname)(int fd, struct sockaddr *addr, unsigned int *addrlen);\n        int (*getpeername)(int fd, struct sockaddr *addr, unsigned int *addrlen);\n\n\n        /* Terminal operations */\n        void (*tty_attach)(struct fnode *fno, int pid);\n        int (*tty_getsid)(struct fnode *fno);\n        int (*tcsetattr)(int td, int opts, const struct termios *tp);\n        int (*tcgetattr)(int td, struct termios *tp);\n\n        /* Block device operations */\n        int (*block_read)(struct fnode *fno, void *buf, uint32_t sector, int offset, int count);\n        int (*block_write)(struct fnode *fno, const void *buf, uint32_t sector, int offset, int count);\n\n    } ops;\n    struct module *next;\n};\n\n\nvoid task_run(void);\nvoid kernel_task_init(void);\n\n\n\n#define kalloc(x) f_malloc(MEM_KERNEL,x)\n#define task_space_alloc(x) f_malloc(MEM_TASK, x)\n#define kcalloc(x,y) f_calloc(MEM_KERNEL,x,y)\n#define krealloc(x,y) f_realloc(MEM_KERNEL,x,y)\n#define kfree  f_free\n#define task_space_free f_free\n#define F_MALLOC_OVERHEAD 24\n\nint mem_lock(void);\nint mem_trylock(void);\nvoid mem_unlock(void);\nuint32_t mem_stats_frag(int pool);\nint fmalloc_owner(const void *ptr);\nint fmalloc_chown(const void *ptr, uint16_t pid);\n\n/* Helper defined by sysfs.c */\nint ul_to_str(unsigned long n, char *s);\nint sysfs_register(char *name, char *dir,\n        int (*do_read)(struct sysfs_fnode *sfs, void *buf, int len),\n        int (*do_write)(struct sysfs_fnode *sfs, const void *buf, int len) );\nvoid sysfs_lock(void);\nvoid sysfs_unlock(void);\nvoid frosted_tcpip_wakeup(void);\nvoid pico_lock_init(void);\nint pico_trylock_kernel(void);\nvoid pico_lock(void);\nint pico_trylock(void);\nvoid pico_unlock(void);\nvoid frost(uint32_t interval);\nvoid defrost(void);\n\n#endif /* BSP_INCLUDED_H */\n\n"
  },
  {
    "path": "kernel/fs/fatfs.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *      Authors: brabo\n *\n */\n\n#include <stdint.h>\n#include \"string.h\"\n#include \"frosted.h\"\n\nstatic struct module mod_fatfs = { };\n\nstruct fatfs_disk {\n    struct fnode *blockdev;\n    struct fnode *mountpoint;\n    struct fatfs *fs;\n};\n\nstruct fatfs_priv {\n    uint32_t            sclust;\n    uint32_t            cclust;\n    uint32_t            sect;\n    uint32_t            off;\n    uint32_t            dirsect;\n    struct fatfs_disk   *fsd;\n    uint32_t            *fat;\n    uint32_t            flags;\n};\n\nstruct fatfs {\n    int         fd;\n    uint8_t     win[512];\n    uint32_t    bsect;\n    uint8_t     type;\n    uint16_t    bps;\n    uint8_t     spc;\n    uint32_t    database;\n    uint32_t    fatbase;\n    uint32_t    dirbase;\n    uint32_t    n_fatent;\n    uint32_t    nclusts;\n    uint8_t     mounted;\n};\n\nstruct fatfs_dir {\n    uint8_t     *fn;\n    uint32_t    sclust;\n    uint32_t    cclust;\n    uint32_t    sect;\n    uint32_t    off;\n    uint32_t    dirsect;\n    uint32_t    attr;\n    uint32_t    fsize;\n};\n\n#ifdef CONFIG_FAT32\n# define FATFS_FAT32    1\n#endif\n\n#ifndef FATFS_FAT32\n# define FATFS_FAT32 0\n#endif\n\n/* Macro proxies for disk operations */\n#define disk_read(f,b,s,o,l) f->blockdev->owner->ops.block_read(f->blockdev,b,s,o,l)\n#define disk_write(f,b,s,o,l) f->blockdev->owner->ops.block_write(f->blockdev,b,s,o,l)\n\n/* BIOS Parameter Block */\n#define BPB_BPS         11\n#define BPB_SPC         13\n#define BPB_RSVD_SEC    14\n#define BPB_NUMFATS     16\n#define BPB_ROOTENTS    17\n#define BPB_TOTSEC16    19\n#define BPB_FATSz16     22\n#define BPB_TOTSEC32    32\n#define BPB_FATSz32     36\n#define BPB_ROOTCLUS    44\n\n/* Boot sector */\n#define BS_JMPBOOT      0\n#define BS_FSTYPE       54\n#define BS_FSTYPE32     82\n#define BS_MBR          446\n#define BS_BS           454\n#define BS_55AA         510\n\n#define DEFBPS          512\n#define FAT_SIG         0xAA55\n\n/* Directory entries */\n#define DIR_NAME        0\n#define DIR_ATTR        11\n#define DIR_SCLUST_HI   20\n#define DIR_SCLUST_LO   26\n#define DIR_FSIZE       28\n\n#define AM_DIR  0x10\n\n#define FAT12   1\n#define FAT16   2\n#define FAT32   3\n#define EOC32   0x0FFFFFF8\n#define DDEM    0xE5\n\n#define PATHN_MAX 256\n#define SFN_MAX     12\n\n/* Entry sizes in bytes */\n#define FATENT_SIZE  4\n#define DIRENT_SIZE  0x20\n\n#define LD_WORD(ptr)        (uint16_t)(*(uint16_t *)(ptr))\n#define LD_DWORD(ptr)       (uint32_t)(*(uint32_t *)(ptr))\n\n#define CLUST2SECT(f, c) (((c - 2) * f->spc + f->database))\n\nint fatfs_truncate(struct fnode *fno, unsigned int len);\n\nstatic void st_word(uint8_t *ptr, uint16_t val)  /* Store a 2-byte word in little-endian */\n{\n    *ptr++ = (uint8_t)val;\n    val >>= 8;\n    *ptr++ = (uint8_t)val;\n}\n\nstatic void st_dword(uint8_t *ptr, uint32_t val)    /* Store a 4-byte word in little-endian */\n{\n    *ptr++ = (uint8_t)val;\n    val >>= 8;\n    *ptr++ = (uint8_t)val;\n    val >>= 8;\n    *ptr++ = (uint8_t)val;\n    val >>= 8;\n    *ptr++ = (uint8_t)val;\n}\n\nstatic int check_fs(struct fatfs_disk *fsd)\n{\n    if (!fsd)\n        return -EINVAL;\n\n    struct fatfs *fs = fsd->fs;\n    if (LD_WORD(fs->win + BS_55AA) != FAT_SIG) {\n        return -ENOMEDIUM;\n    }\n\n    if (fs->win[BS_JMPBOOT] == 0xE9 || (fs->win[BS_JMPBOOT] == 0xEB && fs->win[BS_JMPBOOT + 2] == 0x90)) {\n\n        if ((LD_DWORD(fs->win + BS_FSTYPE32) == 0x33544146) && (*(fs->win + BS_FSTYPE32 + 4) == '2')) {\n            fs->type = FAT32;\n            return 0;\n        }\n    }\n\n    return -EMEDIUMTYPE;\n}\n\nint get_fat(struct fatfs_disk *fsd, int clust)\n{\n    if (!fsd)\n        return -EINVAL;\n\n    struct fatfs *fs = fsd->fs;\n\n    if (clust < 2 || clust >= fs->n_fatent) { /* Range check */\n        return -EINVAL;\n    }\n\n    switch(fs->type) {\n    case FAT12:\n        break;\n    case FAT16:\n        break;\n    case FAT32:\n        if (disk_read(fsd, fs->win, (fs->fatbase + (clust / (fs->bps / FATENT_SIZE))), 0, fs->bps) < 0)\n            break;\n        return (LD_DWORD(fs->win + ((clust * FATENT_SIZE) & (fs->bps - 1))) & 0x0FFFFFFF);\n    }\n    return -EMEDIUMTYPE;\n}\n\nint set_fat(struct fatfs_disk *fsd, uint32_t clust, uint32_t val)\n{\n    if (!fsd)\n        return -EINVAL;\n\n    struct fatfs *fs = fsd->fs;\n\n    if (clust < 2 || clust >= fs->n_fatent) { /* Range check */\n        return -EINVAL;\n    }\n\n    switch(fs->type) {\n    case FAT12:\n        break;\n    case FAT16:\n        break;\n    case FAT32:\n        if (disk_read(fsd, fs->win, (fs->fatbase + (clust / (fs->bps / FATENT_SIZE))), 0, fs->bps) < 0)\n            break;\n        st_dword((fs->win + ((clust * FATENT_SIZE) & (fs->bps - 1))), (uint32_t)(val & 0x0FFFFFFF));\n        disk_write(fsd, fs->win, (fs->fatbase + (clust / (fs->bps / FATENT_SIZE))), 0, fs->bps);\n        return 0;\n    }\n    return -EMEDIUMTYPE;\n}\n\nstatic int get_clust(struct fatfs *fs, uint8_t *dir)\n{\n    if (!fs || !dir)\n        return -EINVAL;\n\n    int clst = 0;\n\n    if (fs->type == FAT32) {\n        clst = LD_WORD(dir + DIR_SCLUST_HI);\n        clst <<= 16;\n    }\n    clst |= LD_WORD(dir + DIR_SCLUST_LO);\n\n    return clst;\n}\n\nint set_clust(struct fatfs *fs, uint8_t *dir, uint32_t clust)\n{\n    if (!fs || !dir)\n        return -EINVAL;\n\n    if (fs->type == FAT32) {\n        st_word((dir + DIR_SCLUST_HI), (clust >> 16));\n    }\n    st_word((dir + DIR_SCLUST_LO), (clust & 0xFFFF));\n\n    return 0;\n}\n\nstatic int walk_fat(struct fatfs_disk *fsd)\n{\n    if (!fsd)\n        return -EINVAL;\n\n    int fat;\n    int clust = 2;\n\n    while (2 > 1) {\n        fat = get_fat(fsd, clust);\n        if (!fat)\n            break;\n        clust++;\n    }\n\n    return clust;\n}\n\nstatic int init_fat(struct fatfs_disk *fsd)\n{\n    if (!fsd)\n        return -EINVAL;\n\n    struct fatfs *fs = fsd->fs;\n\n    int clust = walk_fat(fsd);\n\n    st_dword((fs->win + ((clust * FATENT_SIZE) & (fs->bps - 1))), 0x0FFFFFFF);\n    disk_write(fsd, fs->win, (fs->fatbase + (clust / (fs->bps / FATENT_SIZE))), 0, fs->bps);\n\n    return clust;\n}\n\nstatic int dir_rewind(struct fatfs *fs, struct fatfs_dir *dj)\n{\n    if (!fs || !dj)\n        return -EINVAL;\n\n   if (dj->cclust == 1 || dj->cclust >= fs->n_fatent)\n        return -EINVAL;\n\n    if (!dj->cclust)\n        dj->sect = fs->dirbase;\n    else\n        dj->sect = CLUST2SECT(fs, dj->cclust);\n\n    dj->off = 0 - DIRENT_SIZE;\n\n    return 0;\n}\n\nstatic int dir_read(struct fatfs_disk *fsd, struct fatfs_dir *dj)\n{\n    if (!fsd || !dj)\n        return -EINVAL;\n\n    struct fatfs *fs = fsd->fs;\n\n    dj->off += DIRENT_SIZE;\n    if (dj->off >= fs->bps) {\n        dj->sect++;\n        dj->off = 0;\n    }\n\n    disk_read(fsd, fs->win, (dj->sect), 0, fs->bps);\n\n    /* have to check cluster borders! */\n    while (2 > 1) {\n        uint8_t *off = fs->win + dj->off;\n        if (!*off) /* Free FAT entry, no more FAT entries! */\n            return -2;\n\n        if (off[0] == DDEM) {\n            dj->off += DIRENT_SIZE;\n            continue;\n        }\n\n        if (*(off + DIR_ATTR) & 0x0F) { /* LFN entry */\n            dj->off += DIRENT_SIZE;\n            continue;\n        }\n\n        int i;\n        char *p = dj->fn;\n        memset(dj->fn, 0x00, (SFN_MAX + 1));\n        char c;\n\n        for (i = 0; i < 8; i++) {   /* Copy file name body */\n            c = off[i];\n            if (c == ' ') break;\n            if (c == 0x05) c = 0xE5;\n            *p++ = c;\n        }\n\n        if (off[8] != ' ') {        /* Copy file name extension */\n            *p++ = '.';\n            for (i = 8; i < 11; i++) {\n                c = off[i];\n                if (c == ' ') break;\n                *p++ = c;\n            }\n        }\n\n        dj->attr = *(off + DIR_ATTR);\n        dj->sclust = get_clust(fs, off);\n        dj->fsize = LD_DWORD(off + DIR_FSIZE);\n        dj->dirsect = dj->sect;\n\n        break;\n    }\n\n    return 0;\n}\n\nstatic int add_dir(struct fatfs *fs, struct fatfs_dir *dj, char *name)\n{\n    if (!fs || !dj || !name)\n        return -EINVAL;\n\n    int nlen = strlen(name);\n    if (nlen > SFN_MAX)\n        return -ENAMETOOLONG;\n\n    memset((fs->win + dj->off), 0, DIRENT_SIZE);\n    memset((fs->win + dj->off), ' ', 11);\n\n    int len = 0;\n    while (len < nlen) {\n        *(fs->win + dj->off + len) = name[len++];\n    }\n\n    *(fs->win + dj->off + DIR_ATTR) = DIRENT_SIZE;\n    st_dword((fs->win + dj->off + DIR_FSIZE), 0);\n    dj->dirsect = dj->sect;\n\n    return 0;\n}\n\nstatic char *relative_path(struct fatfs_disk *f, char *abs)\n{\n    if (!f || !abs)\n        return NULL;\n\n    return (abs + strlen(f->mountpoint->fname) + 1);\n}\n\nstatic void fatfs_populate(struct fatfs_disk *f, char *path, uint32_t clust)\n{\n    if (!f || !path)\n        return;\n\n    char fbuf[SFN_MAX + 1];\n    struct fatfs_priv *priv;\n    struct fatfs_dir dj;\n    struct fnode *parent;\n    char fpath[PATHN_MAX];\n\n    fno_fullpath(f->mountpoint, fpath, PATHN_MAX);\n\n    if (path && strlen(path) > 0) {\n        if (path[0] != '/')\n            strcat(fpath, \"/\");\n        strcat(fpath, path);\n    }\n\n    parent = fno_search(fpath);\n    parent->priv = (void *)kalloc(sizeof(struct fatfs_priv));\n    ((struct fatfs_priv *)parent->priv)->fsd = f;\n\n    dj.fn = fbuf;\n    dj.cclust = clust;\n    dj.sclust = clust;\n    dj.off = 0 - DIRENT_SIZE;\n\n    dir_rewind(f->fs, &dj);\n\n    while(dir_read(f, &dj) == 0) {\n       if (!strncmp(dj.fn, \".\", 2) || !strncmp(dj.fn, \"..\", 3))\n            continue;\n\n        struct fnode *newdir;\n\n        if (dj.attr & AM_DIR)\n            newdir = fno_mkdir(&mod_fatfs, dj.fn, parent);\n        else\n            newdir = fno_create(&mod_fatfs, dj.fn, parent);\n\n        if (!newdir)\n            continue;\n\n        newdir->priv = (void *)kalloc(sizeof(struct fatfs_priv));\n        if (!newdir->priv) {\n            fno_unlink(newdir);\n            continue;\n        }\n\n        priv = newdir->priv;\n        priv->sclust = dj.sclust;\n        priv->cclust = dj.cclust;\n        priv->sect = dj.sect;\n        priv->fsd = f;\n        priv->off = dj.off;\n        priv->dirsect = dj.dirsect;\n\n        newdir->size = dj.fsize;\n\n        int i = 0;\n        uint32_t nclust = newdir->size / (f->fs->spc * f->fs->bps);\n        priv->fat = kcalloc(sizeof (uint32_t), nclust + 1);\n        uint32_t tmpclust = priv->sclust;\n        priv->fat[i++] = tmpclust;\n        while (nclust > 0) {\n            priv->fat[i] = get_fat(f, tmpclust);\n            tmpclust = priv->fat[i++];\n            nclust--;\n        }\n\n        if (dj.attr & AM_DIR) {\n            char fullpath[PATHN_MAX];\n            strncpy(fullpath, fpath, PATHN_MAX);\n            strcat(fullpath, \"/\");\n            strcat(fullpath, dj.fn);\n            path = relative_path(f, fullpath);\n            fatfs_populate(f, path, get_clust(f->fs, (f->fs->win + dj.off)));\n        }\n    }\n}\n\nint fatfs_mount(char *source, char *tgt, uint32_t flags, void *arg)\n{\n    if (!source || !tgt)\n        return -EINVAL;\n\n    struct fnode *tgt_dir = NULL;\n    struct fnode *src_dev = NULL;\n\n    struct fatfs_disk *fsd;\n\n    tgt_dir = fno_search(tgt);\n    src_dev = fno_search(source);\n\n    if (!tgt_dir)\n        return -ENOENT;\n     if ((tgt_dir->flags & FL_DIR) == 0)\n        return -ENOTDIR;\n\n    if (!src_dev || !(src_dev ->owner) || ((src_dev->flags & FL_BLK) == 0)) {\n        /* Invalid block device. */\n        return -ENOENT;\n    }\n\n    /* Initialize file system to disk association */\n    fsd = kcalloc(sizeof(struct fatfs_disk), 1);\n    if (!fsd)\n        return -ENOMEM;\n\n    /* Associate the disk device */\n    fsd->blockdev = src_dev;\n\n    /* Associate a newly created fat filesystem */\n    fsd->fs = kcalloc(sizeof(struct fatfs), 1);\n    if (!fsd->fs) {\n        kfree(fsd);\n        return -ENOMEM;\n    }\n\n    struct fatfs *fs = fsd->fs;\n    /* do we still need this?? */\n    fs->mounted = 0;\n\n    /* Associate the mount point */\n    fsd->mountpoint = tgt_dir;\n    tgt_dir->owner = &mod_fatfs;\n    fs->bsect = 0;\n\n    disk_read(fsd, fs->win, fs->bsect, 0, DEFBPS);\n\n    if (check_fs(fsd) == -EMEDIUMTYPE) {\n        fs->bsect = LD_WORD(fs->win + BS_BS);\n        disk_read(fsd, fs->win, fs->bsect, 0, DEFBPS);\n\n        if (check_fs(fsd) < 0) {\n            goto fail;\n        }\n    }\n\n    uint8_t num_fats = 0;\n    uint16_t root_ents = 0, rsvd_sec = 0;\n    uint32_t root_secs = 0, fatsz = 0, totsec = 0, datasec = 0;\n\n    fs->bps = LD_WORD(fs->win + BPB_BPS);\n    fs->spc = fs->win[BPB_SPC];\n\n    root_ents = LD_WORD(fs->win + BPB_ROOTENTS);\n    root_secs = ((root_ents * 32) + (fs->bps -1)) / fs->bps;\n\n    fatsz = LD_WORD(fs->win + BPB_FATSz16);\n    if (!fatsz)\n        fatsz = LD_DWORD(fs->win + BPB_FATSz32);\n\n    num_fats = fs->win[BPB_NUMFATS];\n    rsvd_sec = LD_WORD(fs->win + BPB_RSVD_SEC);\n    fs->database = rsvd_sec + (num_fats * fatsz) + root_secs;\n    fs->database += fs->bsect;\n\n    totsec = LD_WORD(fs->win + BPB_TOTSEC16);\n    if (!totsec)\n        totsec = LD_DWORD(fs->win + BPB_TOTSEC32);\n\n    datasec = totsec - (rsvd_sec + (num_fats * fatsz) + root_secs);\n    fs->nclusts = datasec / fs->spc;\n    fs->fatbase = rsvd_sec + fs->bsect;\n    fs->dirbase = CLUST2SECT(fs, LD_DWORD(fs->win + BPB_ROOTCLUS));\n\n    /* FAT type determination */\n    if (fs->nclusts < 4085)\n        fs->type = FAT12;\n    else if (fs->nclusts < 65525)\n        fs->type = FAT16;\n    else\n        fs->type = FAT32;\n\n    fs->n_fatent = fs->nclusts + 2;\n\n    fatfs_populate(fsd, \"\", 0);\n    fs->mounted = 1;\n\n    return 0;\n\nfail:\n    kfree(fsd->fs);\n    kfree(fsd);\n\n    return -ENOMEDIUM;\n}\n\nint fatfs_open(const char *path, int flags)\n{\n    struct fnode *fno = fno_search(path);\n    struct fatfs_priv *priv = (struct fatfs_priv *)fno->priv;\n    int ret;\n\n    if (!path)\n        return -EINVAL;\n\n    fno = fno_search(path);\n    if (!fno)\n        return -ENOENT;\n\n    priv = (struct fatfs_priv *)fno->priv;\n    priv->flags = flags;\n\n    if (flags & O_TRUNC) {\n        fatfs_truncate(fno, 0);\n    }\n\n    ret = task_filedesc_add(fno);\n\n    return ret;\n}\n\nstatic int dir_find(struct fatfs_disk *fsd, struct fatfs_dir *dj, char *path)\n{\n    if (!fsd || !dj || !path)\n        return -EINVAL;\n\n    while (dir_read(fsd, dj) == 0) {\n        if (!strncmp(dj->fn, path, SFN_MAX)) {\n            dj->off;\n            uint32_t fat = get_fat(fsd, dj->sclust);\n            dj->sect = CLUST2SECT(fsd->fs, dj->sclust);\n            dj->cclust = dj->sclust;\n            return 0;\n        }\n    }\n\n    return -ENOENT;\n}\n\nstatic int follow_path(struct fatfs_disk *fsd, struct fatfs_dir *dj, char *path)\n{\n    if (!fsd || !dj || !path)\n        return -EINVAL;\n\n    int res;\n\n    if (!strncmp(path, \"/mnt\", 4))\n        path += 4;\n\n    while (*path == ' ')\n        path++;\n\n    if (*path == '/')\n        path++;\n\n    dj->cclust = 0;\n\n    res = dir_rewind(fsd->fs, dj);\n    if (*path < ' ') {\n        dj->off = 0 - DIRENT_SIZE;\n        return res;\n    }\n\n    dj->off = 0 - DIRENT_SIZE;\n\n    do {\n        char tpath[SFN_MAX + 1];\n        char *tpathp = tpath;\n\n        while ((*path != '/') && (*path != ' ') && (*path != 0x00)) {\n            *tpathp++ = *path++;\n        }\n\n        *tpathp = 0x00;\n        res = dir_find(fsd, dj, tpath);\n        if (*path == '/')\n            path++;\n    } while ((*path != ' ') && (*path != 0x00));\n\n    return res;\n}\n\nint fatfs_creat(struct fnode *fno)\n{\n    if (!fno || !fno->parent || !fno->parent->priv)\n        return -EINVAL;\n\n    if (!((struct fatfs_priv *)fno->parent->priv)->fsd->fs->mounted)\n        return -EINVAL;\n\n    struct fatfs_dir dj;\n    char fbuf[SFN_MAX + 1];\n    char *path = kalloc(PATHN_MAX * sizeof (char));\n\n    fno_fullpath(fno, path, PATHN_MAX);\n\n    struct fatfs_priv *priv = (struct fatfs_priv *)fno->priv;\n\n    if (!priv) {\n        priv = (void *)kalloc(sizeof (struct fatfs_priv));\n        priv->fsd = ((struct fatfs_priv *)fno->parent->priv)->fsd;\n    }\n\n    struct fatfs *fs = priv->fsd->fs;\n    struct fatfs_disk *fsd = priv->fsd;\n    fno->priv = priv;\n    dj.fn = fbuf;\n    dj.off = 0 - DIRENT_SIZE;\n\n    uint32_t clust = init_fat(fsd);\n    follow_path(fsd, &dj, path);\n\n    while ((*path != ' ') && (*path != 0x00))\n        path++;\n    while (*path != '/')\n        path--;\n    path++;\n\n    int ret = add_dir(fs, &dj, path);\n    set_clust(fs, (fs->win + dj.off), clust);\n    disk_write(fsd, fs->win, dj.sect, 0, fs->bps);\n\n    priv->sclust = priv->cclust = clust;\n    priv->fat = kcalloc(3, sizeof (uint32_t));\n    priv->fat[0] = priv->sclust;\n    priv->sect = CLUST2SECT(fs, priv->cclust);\n    priv->off = dj.off;\n    fno->size = 0;\n    priv->dirsect = dj.dirsect;\n\n    return 0;\n}\n\nint fatfs_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    if (!fno || !fno->priv)\n        return -EINVAL;\n\n    struct fatfs_priv *priv = (struct fatfs_priv *)fno->priv;\n    struct fatfs_disk *fsd = priv->fsd;\n    struct fatfs *fs = fsd->fs;\n\n    int r_len = 0, sect = 0, off = 0, clust = 0;\n    uint32_t cur_off = task_fd_get_off(fno);\n\n    off = cur_off;\n    sect = off / fs->bps;\n    off = off & (fs->bps - 1);\n    clust = sect / fs->spc;\n    sect = sect & (fs->spc - 1);\n\n    priv->cclust = priv->fat[clust];\n    priv->sect = CLUST2SECT(fs, priv->cclust);\n\n    while ((r_len < len) && (cur_off < fno->size)) {\n        int r = len - r_len;\n        if (r > fs->bps)\n            r = fs->bps;\n\n        if ((r == fs->bps) && off > 0)\n            r -= off;\n\n        if (cur_off + r > fno->size)\n            r = fno->size - cur_off;\n\n        /* XXX: use returned value, maybe lower level returned less.. */\n        disk_read(fsd, ((uint8_t *)buf + r_len), (priv->sect + sect), off, r);\n\n        r_len += r;\n        off += r;\n        cur_off += r;\n        task_fd_set_off(fno, cur_off);\n\n        if ((r_len < len) && (off == fs->bps) && (cur_off < fno->size)) {\n            sect++;\n            if ((sect) >= fs->spc) {\n                clust++;\n                priv->cclust = priv->fat[clust];\n                priv->sect = CLUST2SECT(fs, priv->cclust);\n                sect = 0;\n            }\n        }\n        off = 0;\n    }\n\n    return r_len;\n}\n\nint fatfs_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    if (!fno || !fno->priv)\n        return -EINVAL;\n\n    struct fatfs_priv *priv = (struct fatfs_priv *)fno->priv;\n    struct fatfs_disk *fsd = priv->fsd;\n    struct fatfs *fs = fsd->fs;\n    uint32_t cur_off;\n    int w_len = 0, sect = 0, clust = 0, off = 0;\n    cur_off = task_fd_get_off(fno);\n\n    if (priv->flags & O_APPEND) {\n        off = fno->size;\n        cur_off = off;\n    } else {\n        off = cur_off;\n    }\n\n    task_fd_set_off(fno, cur_off);\n\n    sect = off / fs->bps;\n    off = off & (fs->bps - 1);\n    clust = sect / fs->spc;\n    sect = sect & (fs->spc - 1);\n\n    priv->cclust = priv->fat[clust];\n    priv->sect = CLUST2SECT(fs, priv->cclust);\n\n    while (w_len < len) {\n        int r = len - w_len;\n        if (r > fs->bps)\n            r = fs->bps;\n\n        if ((r == fs->bps) && off > 0)\n            r -= off;\n\n        disk_write(fsd, ((uint8_t *)buf) + w_len, (priv->sect + sect), off, r);\n        w_len += r;\n        off += r;\n        cur_off += r;\n        task_fd_set_off(fno, cur_off);\n        if ((w_len < len) && (off == fs->bps)) {\n            sect++;\n            if ((sect) >= fs->spc) {\n                clust++;\n                sect = 0;\n                if (cur_off <= fno->size) {\n                    priv->cclust = priv->fat[clust];\n                } else {\n                    uint32_t tempclust = priv->cclust;\n                    priv->cclust = init_fat(fsd);\n\n                    uint32_t *tmp = krealloc(priv->fat, ((sizeof (uint32_t)) * (clust + 1)));\n                    if (!tmp)\n                        return -EAGAIN;\n\n                    priv->fat = tmp;\n                    priv->fat[clust] = priv->cclust;\n                    set_fat(fsd, tempclust, priv->cclust);\n                }\n                priv->sect = CLUST2SECT(fs, priv->cclust);\n            }\n        }\n        off = 0;\n    }\n    if (cur_off > fno->size) {\n        fno->size = cur_off;\n        disk_read(fsd, fs->win, priv->dirsect, 0, fs->bps);\n        st_dword((fs->win + priv->off + DIR_FSIZE), (uint32_t)fno->size);\n        disk_write(fsd, fs->win, priv->dirsect, 0, fs->bps);\n    }\n    return w_len;\n}\n\nint fatfs_seek(struct fnode *fno, int off, int whence)\n{\n    int new_off;\n    if (!fno)\n        return -EINVAL;\n\n    switch (whence) {\n        case SEEK_CUR:\n            new_off = task_fd_get_off(fno) + off;\n            break;\n        case SEEK_SET:\n            new_off = off;\n            break;\n        case SEEK_END:\n            new_off = fno->size + off;\n            break;\n        default:\n            return -EINVAL;\n    }\n\n    if (new_off < 0)\n        new_off = 0;\n\n    if (new_off > fno->size)\n        return -ESPIPE;\n\n    task_fd_set_off(fno, new_off);\n    return new_off;\n}\n\nint fatfs_truncate(struct fnode *fno, unsigned int len)\n{\n    if (!fno)\n        return -EINVAL;\n\n    int new_size;\n\n    new_size = len;\n\n    if (new_size < 0)\n        new_size = 0;\n\n    if (new_size > fno->size)\n        return -ESPIPE;\n\n    fno->size = new_size;\n\n    return 0;\n}\n\nint fatfs_unlink(struct fnode *fno)\n{\n    if (!fno || !fno->priv)\n        return -EINVAL;\n\n    struct fatfs_priv *priv = (struct fatfs_priv *)fno->priv;\n    struct fatfs_disk *fsd = priv->fsd;\n    struct fatfs *fs = fsd->fs;\n\n    disk_read(fsd, fs->win, priv->dirsect, 0, fs->bps);\n    fs->win[priv->off] = DDEM;\n    disk_write(fsd, fs->win, priv->dirsect, 0, fs->bps);\n}\n\nint fatfs_close(struct fnode *fno)\n{\n    if (!fno)\n        return -EINVAL;\n    return 0;\n}\n\nint fatfs_init(void)\n{\n    mod_fatfs.family = FAMILY_FILE;\n    strcpy(mod_fatfs.name,\"fatfs\");\n\n    mod_fatfs.mount = fatfs_mount;\n    mod_fatfs.ops.open = fatfs_open;\n    mod_fatfs.ops.creat = fatfs_creat;\n    mod_fatfs.ops.read = fatfs_read;\n    mod_fatfs.ops.write = fatfs_write;\n    mod_fatfs.ops.seek = fatfs_seek;\n    mod_fatfs.ops.truncate = fatfs_truncate;\n    mod_fatfs.ops.close = fatfs_close;\n    mod_fatfs.ops.unlink = fatfs_unlink;\n\n    register_module(&mod_fatfs);\n    return 0;\n}\n\n\n"
  },
  {
    "path": "kernel/fs/fatfs.h",
    "content": "#include \"frosted.h\"\r\n\r\n#ifndef FATFS_INC\r\n#define FATFS_INC\r\n\r\n\r\n#ifdef CONFIG_FATFS\r\n\r\nint fatfs_init(void);\r\n\r\n#else\r\n#define fatfs_init() ((-ENOENT))\r\n\r\n#endif\r\n\r\n\r\n#endif\r\n"
  },
  {
    "path": "kernel/fs/memfs.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"string.h\"\n\nstatic struct module mod_memfs;\n\n\nstruct memfs_fnode {\n    struct fnode *fnode;\n    uint8_t *content;\n};\n\n\nstatic int memfs_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct memfs_fnode *mfno;\n    uint32_t off;\n    if (len <= 0)\n        return len;\n\n    mfno = FNO_MOD_PRIV(fno, &mod_memfs);\n    if (!mfno)\n        return -ENOENT;\n\n    off = task_fd_get_off(fno);\n\n    if (fno->size <= off)\n        return 0;\n\n    if (len > (fno->size - off))\n        len = fno->size - off;\n\n    memcpy(buf, mfno->content + off, len);\n    off+=len;\n    task_fd_set_off(fno, off);\n    return len;\n}\n\n\nstatic int memfs_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    struct memfs_fnode *mfno;\n    uint32_t off;\n    if (len <= 0)\n        return len;\n\n    mfno = FNO_MOD_PRIV(fno, &mod_memfs);\n    if (!mfno)\n        return -ENOENT;\n\n    off = task_fd_get_off(fno);\n\n    if (fno->size < (off+len)) {\n        mfno->content = krealloc(mfno->content, off + len);\n    }\n    if (!mfno->content)\n        return -ENOMEM;\n    memcpy(mfno->content + off, buf, len);\n    off += len;\n    if (fno->size < off)\n        fno->size = off;\n    task_fd_set_off(fno, off);\n    return len;\n}\n\nstatic int memfs_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    *revents = events;\n    return 1;\n}\n\nstatic int memfs_seek(struct fnode *fno, int off, int whence)\n{\n    struct memfs_fnode *mfno;\n    int new_off;\n    mfno = FNO_MOD_PRIV(fno, &mod_memfs);\n    if (!mfno)\n        return -1;\n    switch(whence) {\n        case SEEK_CUR:\n            new_off = task_fd_get_off(fno) + off;\n            break;\n        case SEEK_SET:\n            new_off = off;\n            break;\n        case SEEK_END:\n            new_off = fno->size + off;\n            break;\n        default:\n            return -EINVAL;\n    }\n\n    if (new_off < 0)\n        new_off = 0;\n\n    if (new_off > fno->size) {\n        mfno->content = krealloc(mfno->content, new_off);\n        memset(mfno->content + fno->size, 0, new_off - fno->size);\n        fno->size = new_off;\n    }\n    task_fd_set_off(fno, new_off);\n    return new_off;\n}\n\nstatic int memfs_close(struct fnode *fno)\n{\n    struct memfs_fnode *mfno;\n    mfno = FNO_MOD_PRIV(fno, &mod_memfs);\n    if (!mfno)\n        return -1;\n    return 0;\n}\n\nstatic int memfs_creat(struct fnode *fno)\n{\n    struct memfs_fnode *mfs = kalloc(sizeof(struct memfs_fnode));\n    if (mfs) {\n        mfs->fnode = fno;\n        mfs->content = NULL;\n        fno->priv = mfs;\n        return 0;\n    }\n    return -1;\n\n}\n\nstatic int memfs_unlink(struct fnode *fno)\n{\n    struct memfs_fnode *mfno;\n    if (!fno)\n        return -ENOENT;\n    mfno = fno->priv;\n    if (mfno && mfno->content)\n        kfree(mfno->content);\n    kfree(mfno);\n    return 0;\n}\n\nstatic int memfs_truncate(struct fnode *fno, unsigned int newsize)\n{\n    struct memfs_fnode *mfno;\n    if (!fno)\n        return -ENOENT;\n    mfno = fno->priv;\n    if (mfno) {\n        if (fno->size <= newsize) {\n            /* Nothing to do here. */\n            return 0;\n        }\n        if (newsize == 0) {\n            fno->size = 0;\n            kfree(mfno->content);\n            mfno->content = NULL;\n        } else {\n            mfno->content = krealloc(mfno->content, newsize);\n            fno->size = newsize;\n        }\n        return 0;\n    }\n    return -EFAULT;\n}\n\nstatic int memfs_mount(char *source, char *tgt, uint32_t flags, void *arg)\n{\n    struct fnode *tgt_dir = NULL;\n    /* Source must be NULL */\n    if (source)\n        return -1;\n\n    /* Target must be a valid dir */\n    if (!tgt)\n        return -1;\n\n    tgt_dir = fno_search(tgt);\n\n    if (!tgt_dir || ((tgt_dir->flags & FL_DIR) == 0)) {\n        /* Not a valid mountpoint. */\n        return -1;\n    }\n\n    /* TODO: Check empty dir\n    if (tgt_dir->children) {\n        return -1;\n    }\n    */\n    tgt_dir->owner = &mod_memfs;\n    return 0;\n}\n\nvoid memfs_init(void)\n{\n    mod_memfs.family = FAMILY_FILE;\n    strcpy(mod_memfs.name,\"memfs\");\n\n    mod_memfs.mount = memfs_mount;\n\n    mod_memfs.ops.read = memfs_read;\n    mod_memfs.ops.poll = memfs_poll;\n    mod_memfs.ops.write = memfs_write;\n    mod_memfs.ops.seek = memfs_seek;\n    mod_memfs.ops.creat = memfs_creat;\n    mod_memfs.ops.unlink = memfs_unlink;\n    mod_memfs.ops.close = memfs_close;\n    mod_memfs.ops.truncate = memfs_truncate;\n    register_module(&mod_memfs);\n}\n"
  },
  {
    "path": "kernel/fs/sysfs.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n \n#include \"frosted.h\"\n#include \"string.h\"\n#include \"scheduler.h\"\n#include \"gpio.h\"\n#include \"lowpower.h\"\n\n#define MAX_SYSFS_BUFFER 1024\n\nstatic struct fnode *sysfs;\nstatic struct module mod_sysfs;\n\nstatic mutex_t *sysfs_mutex = NULL;\n\nextern struct mountpoint *MTAB;\nextern struct f_malloc_stats f_malloc_stats[5];\n\n\nvoid sysfs_lock(void)\n{\n    if (sysfs_mutex)\n        mutex_lock(sysfs_mutex);\n}\n\nvoid sysfs_unlock(void)\n{\n    if (sysfs_mutex)\n        mutex_unlock(sysfs_mutex);\n}\n\nstatic int sysfs_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct sysfs_fnode *mfno;\n    if (len <= 0)\n        return len;\n\n    mfno = FNO_MOD_PRIV(fno, &mod_sysfs);\n    if (!mfno)\n        return -1;\n\n    if (mfno->do_read) {\n        return mfno->do_read(mfno, buf, len);\n    }\n    return -1;\n\n}\n\nstatic int sysfs_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    struct sysfs_fnode *mfno;\n    if (len <= 0)\n        return len;\n\n    mfno = FNO_MOD_PRIV(fno, &mod_sysfs);\n    if (!mfno)\n        return -1;\n\n    if (mfno->do_write) {\n        return mfno->do_write(mfno, buf, len);\n    }\n    return -1;\n\n}\n\nstatic int sysfs_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    *revents = events;\n    return 1;\n}\n\nstatic int sysfs_close(struct fnode *fno)\n{\n    struct sysfs_fnode *mfno;\n    mfno = FNO_MOD_PRIV(fno, &mod_sysfs);\n    if (!mfno)\n        return -1;\n    return 0;\n}\n\nint ul_to_str(unsigned long n, char *s)\n{\n    int maxlen = 10;\n    int i;\n    int q = 1;\n\n    if (n == 0) {\n        s[0] = '0';\n        s[1] = '\\0';\n        return 1;\n    }\n\n    for (i = 0; i <= maxlen; i++) {\n        if ((n / q) == 0)\n            break;\n        q*=10;\n    }\n    q /= 10;\n    s[i] = '\\0';\n    maxlen = i;\n\n    for (i = 0; i < maxlen; i++) {\n        int c;\n        c = (n / q);\n        s[i] = '0' + c;\n        n -= (c * q);\n        q /= 10;\n    }\n    return maxlen;\n}\n\n\nint nice_to_str(int8_t n, char *s)\n{\n    int i = 0;\n    if (n == 0) {\n        s[0] = '0';\n        s[1] = '\\n';\n        return 1;\n    }\n\n    if (n == NICE_RT) {\n        s[0] = 'R';\n        s[1] = 'T';\n        s[2] = '\\0';\n        return 2;\n    }\n\n    if (n < 0) {\n        s[i++] = '-';\n        n = 0 - n;\n    }\n    if (n > 20) {\n        s[0] = 'E';\n        s[1] = 'R';\n        s[2] = 'R';\n        s[3] = '\\0';\n        return 3;\n    }\n\n    if (n >= 10) {\n        s[i++] = (n / 10) + '0';\n    }\n    s[i++] = (n % 10) + '0';\n    s[i++] = '\\0';\n    return (i - 1);\n}\n\nint sysfs_time_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    uint32_t off = task_fd_get_off(fno);\n    if (off > 0)\n        return -1;\n\n    off += ul_to_str(jiffies, res);\n\n    res[off++] = '\\r';\n    res[off++] = '\\n';\n    res[off] = '\\0';\n    task_fd_set_off(fno, off);\n    return off;\n}\n\nstatic uint32_t strtou32(const char *ptr) {\n    long long val = 0;\n\n    while(*ptr) {\n        int v = *ptr;\n        if ('0' <= v && v <= '9')\n            v -= '0';\n\n        val = val * 10 + v;\n        ptr++;\n    }\n    return val;\n}\n\nstatic int sysfs_suspend_write(struct sysfs_fnode *sfs, const void *buf, int len)\n{\n    uint32_t interval = strtou32(buf);\n    if (len >= 1 && interval >= 1)\n        lowpower_sleep(0, interval);\n    return len;\n}\n\nstatic int sysfs_standby_write(struct sysfs_fnode *sfs, const void *buf, int len)\n{\n    uint32_t interval = strtou32(buf);\n    if (len >= 1 && interval >= 1)\n        lowpower_sleep(1, interval);\n    return len;\n}\n\n\nstatic int gpio_basename(const uint32_t base, char *name)\n{\n    switch(base) {\n#if defined(STM32F4) || defined(STM32F7)\n        case GPIOA: \n            strcpy(name,\"GPIOA\");\n            return 5;\n        case GPIOB: \n            strcpy(name,\"GPIOB\");\n            return 5;\n        case GPIOC: \n            strcpy(name,\"GPIOC\");\n            return 5;\n        case GPIOD: \n            strcpy(name,\"GPIOD\");\n            return 5;\n        case GPIOE: \n            strcpy(name,\"GPIOE\");\n            return 5;\n        case GPIOF: \n            strcpy(name,\"GPIOF\");\n            return 5;\n        case GPIOG: \n            strcpy(name,\"GPIOG\");\n            return 5;\n        case GPIOH: \n            strcpy(name,\"GPIOH\");\n            return 5;\n        case GPIOI: \n            strcpy(name,\"GPIOI\");\n            return 5;\n        case GPIOJ: \n            strcpy(name,\"GPIOJ\");\n            return 5;\n        case GPIOK: \n            strcpy(name,\"GPIOK\");\n            return 5;\n#endif\n        default:\n            strcpy(name,\"N/A\");\n            return 3;\n    }\n}\n\n#if defined(STM32F4) || defined(STM32F7)\nint sysfs_pins_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    static char *txt;\n    static uint32_t off;\n    int i;\n    int stack_used;\n    char *name;\n    int p_state;\n    int nice;\n    const char legend[]=\"Base\\tPin\\tMode\\tDrive\\tSpeed\\tTrigger\\tOwner\\r\\n\";\n    struct dev_gpio *g =  Gpio_list;\n    uint32_t pin_n = 0;\n    uint32_t cur_off = task_fd_get_off(fno);\n    if (cur_off == 0) {\n        mutex_lock(sysfs_mutex);\n        txt = kalloc((1 + gpio_list_len()) * 80);\n        if (!txt)\n            return -1;\n        off = 0;\n        strcpy(txt, legend);\n        off += strlen(legend);\n        while (g) {\n\n            /* Base */\n            off += gpio_basename(g->base, txt + off);\n            txt[off++] = '\\t';\n            \n            /* Pin */\n            pin_n = 0;\n            while ((1 << pin_n) != g->pin)\n                pin_n ++;\n            off += ul_to_str(pin_n, txt + off);\n            txt[off++] = '\\t';\n\n            /* Mode */\n            switch (g->mode) {\n                case GPIO_MODE_OUTPUT:\n                    txt[off++] = 'O';\n                    txt[off++] = 'U';\n                    txt[off++] = 'T';\n                    break;\n                case GPIO_MODE_INPUT:\n                    txt[off++] = 'I';\n                    txt[off++] = 'N';\n                    break;\n                case GPIO_MODE_ANALOG:\n                    txt[off++] = 'A';\n                    txt[off++] = 'N';\n                    txt[off++] = 'A';\n                    txt[off++] = 'L';\n                    txt[off++] = 'O';\n                    txt[off++] = 'G';\n                    break;\n                case GPIO_MODE_AF:\n                    txt[off++] = 'A';\n                    txt[off++] = 'L';\n                    txt[off++] = 'T';\n                    off += ul_to_str(g->af, txt + off);\n                    break;\n            }\n            txt[off++] = '\\t';\n\n            /* Drive */\n            if (g->optype == GPIO_OTYPE_OD) {\n                txt[off++] = 'O';\n                txt[off++] = 'D';\n                txt[off++] = 'r';\n                txt[off++] = 'a';\n                txt[off++] = 'i';\n                txt[off++] = 'n';\n            } else {\n                switch(g->pullupdown) {\n                    case GPIO_PUPD_PULLUP:\n                        txt[off++] = 'P';\n                        txt[off++] = 'u';\n                        txt[off++] = 'l';\n                        txt[off++] = 'l';\n                        txt[off++] = 'U';\n                        txt[off++] = 'p';\n                        break;\n                    case GPIO_PUPD_PULLDOWN:\n                        txt[off++] = 'P';\n                        txt[off++] = 'u';\n                        txt[off++] = 'l';\n                        txt[off++] = 'l';\n                        txt[off++] = 'D';\n                        txt[off++] = 'w';\n                        break;\n                    default:\n                        txt[off++] = 'N';\n                        txt[off++] = 'o';\n                        txt[off++] = 'n';\n                        txt[off++] = 'e';\n                        break;\n                }\n            } \n            txt[off++] = '\\t';\n\n\n            /* Speed */\n            /* FIXME: if you want to see output speed. */\n            txt[off++] = '-';\n            txt[off++] = '\\t';\n\n            /* Trigger */\n            switch (g->trigger) {\n\n                case GPIO_TRIGGER_RAISE:\n                    txt[off++] = 'R';\n                    txt[off++] = 'a';\n                    txt[off++] = 'i';\n                    txt[off++] = 's';\n                    txt[off++] = 'e';\n                    break;\n\n                case GPIO_TRIGGER_FALL:\n                    txt[off++] = 'F';\n                    txt[off++] = 'a';\n                    txt[off++] = 'l';\n                    txt[off++] = 'l';\n                    break;\n\n                case GPIO_TRIGGER_TOGGLE:\n                    txt[off++] = 'T';\n                    txt[off++] = 'o';\n                    txt[off++] = 'g';\n                    txt[off++] = 'g';\n                    txt[off++] = 'l';\n                    txt[off++] = 'e';\n                    break;\n\n                default:\n                    txt[off++] = 'N';\n                    txt[off++] = 'o';\n                    txt[off++] = 'n';\n                    txt[off++] = 'e';\n                    break;\n            }\n            txt[off++] = '\\t';\n\n            /* Owner's name */\n            strcpy(txt + off, g->owner->name);\n            off += strlen(g->owner->name);\n            txt[off++] = '\\r';\n            txt[off++] = '\\n';\n            g = g->next;\n        }\n        txt[off++] = '\\0';\n    }\n    cur_off = task_fd_get_off(fno);\n    if (off == cur_off) {\n        kfree(txt);\n        mutex_unlock(sysfs_mutex);\n        return -1;\n    }\n    if (len > (off - cur_off)) {\n       len = off - cur_off;\n    }\n    memcpy(res, txt + cur_off, len);\n    task_fd_set_off(fno, cur_off + len);\n    return len;\n}\n#endif\n\nint sysfs_tasks_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    static char *task_txt;\n    static uint32_t off;\n    int i;\n    int stack_used;\n    char *name;\n    int p_state;\n    int nice;\n    const char legend[]=\"pid\\tstate\\tstack\\theap\\tnice\\tname\\r\\n\";\n    uint32_t cur_off = task_fd_get_off(fno);\n    if (cur_off == 0) {\n        mutex_lock(sysfs_mutex);\n        task_txt = kalloc(MAX_SYSFS_BUFFER);\n        if (!task_txt)\n            return -1;\n        off = 0;\n\n        strcpy(task_txt, legend);\n        off += strlen(legend);\n\n        for (i = 1; i <= 0xFFFF; i++) {\n            p_state = scheduler_task_state(i);\n            if ((p_state != TASK_IDLE) && (p_state != TASK_OVER)) {\n                off += ul_to_str(i, task_txt + off);\n                task_txt[off++] = '\\t';\n                if (p_state == TASK_RUNNABLE)\n                    task_txt[off++] = 'r';\n                if (p_state == TASK_RUNNING)\n                    task_txt[off++] = 'R';\n                if (p_state == TASK_WAITING)\n                    task_txt[off++] = 'W';\n                if (p_state == TASK_FORKED)\n                    task_txt[off++] = 'F';\n                if (p_state == TASK_ZOMBIE)\n                    task_txt[off++] = 'Z';\n                if (p_state == TASK_STOPPED)\n                    task_txt[off++] = 'S';\n\n                task_txt[off++] = '\\t';\n                stack_used = scheduler_stack_used(i);\n                off += ul_to_str(stack_used, task_txt + off);\n                \n                task_txt[off++] = '\\t';\n                stack_used = f_proc_heap_count(i);\n                off += ul_to_str(stack_used, task_txt + off);\n                \n                task_txt[off++] = '\\t';\n                nice = scheduler_get_nice(i);\n                off += nice_to_str(nice, task_txt + off);\n\n                task_txt[off++] = '\\t';\n                name = scheduler_task_name(i);\n                if (name)\n                {\n                    strcpy(&task_txt[off], name);\n                    off += strlen(name);\n                }\n\n                task_txt[off++] = '\\r';\n                task_txt[off++] = '\\n';\n            }\n        }\n        task_txt[off++] = '\\0';\n    }\n\n    cur_off = task_fd_get_off(fno);\n    if (off == cur_off) {\n        kfree(task_txt);\n        mutex_unlock(sysfs_mutex);\n        return -1;\n    }\n    if (len > (off - cur_off)) {\n       len = off - cur_off;\n    }\n    memcpy(res, task_txt + cur_off, len);\n    cur_off += len;\n    task_fd_set_off(fno, cur_off);\n    return len;\n}\n\n#define NPOOLS 5\n\nint sysfs_mem_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    static char *mem_txt;\n    static int off;\n    int i;\n    int stack_used;\n    int p_state;\n    uint32_t cur_off = task_fd_get_off(fno);\n    if (cur_off == 0) {\n        const char mem_stat_banner[NPOOLS][50] = {\"\\r\\nKernel memory statistics\\r\\n\",\n                                          \"\\r\\n\\nUser memory statistics\\r\\n\",\n                                          \"\\r\\n\\nTask space statistics\\r\\n\",\n                                          \"\\r\\n\\nTCP/IP space statistics\\r\\n\",\n                                          \"\\r\\n\\nExtra mem space statistics\\r\\n\",\n\n        };\n\n        const char malloc_banner[] = \"\\tObjects in use: \";\n        const char mem_banner[] = \"\\tMemory in use: \";\n        const char frags_banner[] = \"\\tReserved: \";\n        int i;\n        mutex_lock(sysfs_mutex);\n        mem_txt = kalloc(MAX_SYSFS_BUFFER);\n        if (!mem_txt)\n            return -1;\n        off = 0;\n\n        for (i = 0; i < NPOOLS; i++) {\n            unsigned long allocated = f_malloc_stats[i].malloc_calls - f_malloc_stats[i].free_calls;\n            strcpy(mem_txt + off, mem_stat_banner[i]);\n            off += strlen(mem_stat_banner[i]);\n            strcpy(mem_txt + off, malloc_banner);\n            off += strlen(malloc_banner);\n            off += ul_to_str(allocated, mem_txt + off);\n            *(mem_txt + off) = '\\r';\n            off++;\n            *(mem_txt + off) = '\\n';\n            off++;\n\n            strcpy(mem_txt + off, mem_banner);\n            off += strlen(mem_banner);\n            off += ul_to_str(f_malloc_stats[i].mem_allocated, mem_txt + off);\n\n            *(mem_txt + off) = ' ';\n            off++;\n            *(mem_txt + off) = 'B';\n            off++;\n            *(mem_txt + off) = '\\r';\n            off++;\n            *(mem_txt + off) = '\\n';\n            off++;\n\n            strcpy(mem_txt + off, frags_banner);\n            off += strlen(frags_banner);\n            off += ul_to_str(mem_stats_frag(i), mem_txt + off);\n            *(mem_txt + off) = ' ';\n            off++;\n            *(mem_txt + off) = 'B';\n            off++;\n            *(mem_txt + off) = '\\r';\n            off++;\n            *(mem_txt + off) = '\\n';\n            off++;\n        }\n        if (off > 0)\n            mem_txt[off++] = '\\0';\n    }\n    cur_off = task_fd_get_off(fno);\n    if (off == cur_off) {\n        kfree(mem_txt);\n        mutex_unlock(sysfs_mutex);\n        return -1;\n    }\n    if (len > (off - cur_off)) {\n       len = off - cur_off;\n    }\n    memcpy(res, mem_txt + cur_off, len);\n    cur_off += len;\n    task_fd_set_off(fno, cur_off);\n    return len;\n}\n\nint sysfs_modules_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    static char *mem_txt;\n    static int off;\n    int i;\n    int stack_used;\n    int p_state;\n    struct module *m = MODS;\n    uint32_t cur_off = task_fd_get_off(fno);\n    if (cur_off == 0) {\n        const char mod_banner[] = \"Loaded modules:\\r\\n\";\n        mutex_lock(sysfs_mutex);\n        mem_txt = kalloc(MAX_SYSFS_BUFFER);\n        if (!mem_txt)\n            return -1;\n        off = 0;\n        strcpy(mem_txt + off, mod_banner);\n        off += strlen(mod_banner);\n\n        while (m) {\n            strcpy(mem_txt + off, m->name);\n            off += strlen(m->name);\n            *(mem_txt + (off++)) = '\\r';\n            *(mem_txt + (off++)) = '\\n';\n            m = m->next;\n        }\n    }\n    cur_off = task_fd_get_off(fno);\n    if (off == cur_off) {\n        kfree(mem_txt);\n        mutex_unlock(sysfs_mutex);\n        return -1;\n    }\n    if (len > (off - cur_off)) {\n       len = off - cur_off;\n    }\n    memcpy(res, mem_txt + cur_off, len);\n    cur_off += len;\n    task_fd_set_off(fno,cur_off);\n    return len;\n}\n\nint sysfs_mtab_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    char *res = (char *)buf;\n    struct fnode *fno = sfs->fnode;\n    static char *mem_txt;\n    static int off;\n    int i;\n    int stack_used;\n    int p_state;\n    struct mountpoint *m = MTAB;\n    int l = 0;\n    uint32_t cur_off = task_fd_get_off(fno);\n    if (cur_off == 0) {\n        const char mtab_banner[] = \"Mountpoint\\tDriver\\t\\tInfo\\r\\n--------------------------------------\\r\\n\";\n        mutex_lock(sysfs_mutex);\n        mem_txt = kalloc(MAX_SYSFS_BUFFER);\n        if (!mem_txt)\n            return -1;\n        off = 0;\n        strcpy(mem_txt + off, mtab_banner);\n        off += strlen(mtab_banner);\n\n        while (m) {\n            l = fno_fullpath(m->target, mem_txt + off, MAX_SYSFS_BUFFER - off);\n            if (l > 0)\n                off += l;\n            *(mem_txt + (off++)) = '\\t';\n            *(mem_txt + (off++)) = '\\t';\n\n            if (m->target->owner) {\n                strcpy(mem_txt + off, m->target->owner->name);\n                off += strlen(m->target->owner->name);\n            }\n            *(mem_txt + (off++)) = '\\t';\n            *(mem_txt + (off++)) = '\\t';\n\n            l = 0;\n            if (m->target->owner->mount_info) {\n                l = m->target->owner->mount_info(m->target, mem_txt + off, MAX_SYSFS_BUFFER - off);\n            }\n            if (l > 0) {\n                off += l;\n            } else {\n                strcpy(mem_txt + off, \"None\");\n                off += 4;\n            }\n            *(mem_txt + (off++)) = '\\r';\n            *(mem_txt + (off++)) = '\\n';\n\n            m = m->next;\n        }\n        *(mem_txt + (off++)) = '\\r';\n        *(mem_txt + (off++)) = '\\n';\n    }\n    cur_off = task_fd_get_off(fno);\n    if (off == cur_off) {\n        kfree(mem_txt);\n        mutex_unlock(sysfs_mutex);\n        return -1;\n    }\n    if (len > (off - cur_off)) {\n       len = off - cur_off;\n    }\n    memcpy(res, mem_txt + cur_off, len);\n    cur_off += len;\n    task_fd_set_off(fno,cur_off);\n    return len;\n}\n\nint sysfs_no_write(struct sysfs_fnode *sfs, const void *buf, int len)\n{\n    return -1;\n}\n\nint sysfs_no_read(struct sysfs_fnode *sfs, void *buf, int len)\n{\n    return 0;\n}\n\n\nint sysfs_register(char *name, char *dir,\n        int (*do_read)(struct sysfs_fnode *sfs, void *buf, int len),\n        int (*do_write)(struct sysfs_fnode *sfs, const void *buf, int len) )\n{\n    struct fnode *fno = fno_create(&mod_sysfs, name, fno_search(dir));\n    struct sysfs_fnode *mfs;\n    if (!fno)\n        return -1;\n\n    mfs = kalloc(sizeof(struct sysfs_fnode));\n    if (mfs) {\n        mfs->fnode = fno;\n        fno->priv = mfs;\n        mfs->do_read = do_read;\n        mfs->do_write = do_write;\n        return 0;\n    }\n    return -1;\n}\n\nstatic int sysfs_mount(char *source, char *tgt, uint32_t flags, void *args)\n{\n    struct fnode *tgt_dir = NULL;\n    /* Source must be NULL */\n    if (source)\n        return -1;\n\n    /* Target must be a valid dir */\n    if (!tgt)\n        return -1;\n\n    tgt_dir = fno_search(tgt);\n\n    if (!tgt_dir || ((tgt_dir->flags & FL_DIR) == 0)) {\n        /* Not a valid mountpoint. */\n        return -1;\n    }\n\n    /* TODO: check empty dir\n    if (tgt_dir->children) {\n        return -1;\n    }\n    */\n    tgt_dir->owner = &mod_sysfs;\n    sysfs_register(\"time\", \"/sys\", sysfs_time_read, sysfs_no_write);\n    sysfs_register(\"tasks\",\"/sys\",  sysfs_tasks_read, sysfs_no_write);\n    sysfs_register(\"mem\", \"/sys\", sysfs_mem_read, sysfs_no_write);\n    sysfs_register(\"modules\", \"/sys\", sysfs_modules_read, sysfs_no_write);\n    sysfs_register(\"mtab\", \"/sys\", sysfs_mtab_read, sysfs_no_write);\n#if defined(STM32F4) || defined(STM32F7)\n    sysfs_register(\"pins\", \"/sys\", sysfs_pins_read, sysfs_no_write);\n#endif\n#ifdef CONFIG_LOWPOWER\n    sysfs_register(\"suspend\",\"/sys/power\", sysfs_no_read, sysfs_suspend_write);\n    sysfs_register(\"standby\",\"/sys/power\", sysfs_no_read, sysfs_standby_write);\n#endif\n    return 0;\n}\n\n\nvoid sysfs_init(void)\n{\n    mod_sysfs.family = FAMILY_FILE;\n    strcpy(mod_sysfs.name, \"sysfs\");\n\n    mod_sysfs.mount = sysfs_mount;\n\n    mod_sysfs.ops.read = sysfs_read;\n    mod_sysfs.ops.poll = sysfs_poll;\n    mod_sysfs.ops.write = sysfs_write;\n    mod_sysfs.ops.close = sysfs_close;\n\n    sysfs = fno_search(\"/sys\");\n    fno_mkdir(&mod_sysfs, \"net\", sysfs);\n    fno_mkdir(&mod_sysfs, \"power\", sysfs);\n    register_module(&mod_sysfs);\n    sysfs_mutex = mutex_init();\n}\n"
  },
  {
    "path": "kernel/fs/xipfs.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n \n#include \"frosted.h\"\n#include <string.h>\n#include \"bflt.h\"\n#include \"kprintf.h\"\n#include \"sys/fs/xipfs.h\"\n#include \"vfs.h\"\n#define GDB_PATH \"frosted-userland/gdb/\"\n\nstatic struct fnode *xipfs;\nstatic struct module mod_xipfs;\n\nstruct xipfs_fnode {\n    struct fnode *fnode;\n    void (*init)(void *);\n};\n\n\n\n#define SECTOR_SIZE (512)\n\nstatic int xipfs_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    struct xipfs_fnode *xfno;\n    uint32_t off = task_fd_get_off(fno);\n    if (len <= 0)\n        return len;\n\n    xfno = FNO_MOD_PRIV(fno, &mod_xipfs);\n    if (!xfno)\n        return -1;\n\n    if (fno->size <= (off))\n        return -1;\n\n    if (len > (fno->size - off))\n        len = fno->size - off;\n\n    memcpy(buf, ((char *)xfno->init) + off, len);\n    off += len;\n    task_fd_set_off(fno,off);\n    return len;\n}\n\nstatic int xipfs_block_read(struct fnode *fno, void *buf, uint32_t sector, int offset, int count)\n{\n    uint32_t off = sector * SECTOR_SIZE + offset;\n    task_fd_set_off(fno,off);\n    if (off > fno->size) {\n        task_fd_set_off(fno,0);\n        return -1;\n    }\n    if (xipfs_read(fno, buf, count) == count)\n        return 0;\n    return -1;\n}\n\n\n\nstatic int xipfs_write(struct fnode *fno, const void *buf, unsigned int len)\n{\n    return -1; /* Cannot write! */\n}\n\nstatic int xipfs_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    return -1;\n}\n\nstatic int xipfs_seek(struct fnode *fno, int off, int whence)\n{\n    return -1;\n}\n\nstatic int xipfs_close(struct fnode *fno)\n{\n    return 0;\n}\n\nstatic int xipfs_creat(struct fnode *fno)\n{\n    return -1;\n\n}\n\nstatic void *xipfs_exe(struct fnode *fno, void *arg)\n{\n    struct xipfs_fnode *xip = (struct xipfs_fnode *)fno->priv;\n    void *reloc_text, *reloc_data, *reloc_bss;\n    size_t stack_size;\n    void *init = NULL;\n    struct vfs_info *vfsi = NULL;\n\n    if (!xip)\n        return NULL;\n\n    vfsi = f_calloc(MEM_KERNEL, 1u, sizeof(struct vfs_info));\n    if (!vfsi)\n        return NULL;\n\n    /* note: xip->init is bFLT load address! */\n    if (bflt_load((uint8_t*)xip->init, &reloc_text, &reloc_data, &reloc_bss, &init, &stack_size, (uint32_t *)&vfsi->pic, &vfsi->text_size, &vfsi->data_size))\n    {\n        kprintf(\"xipfs: bFLT loading failed.\\n\");\n        return NULL;\n    }\n\n    kprintf(\"xipfs: GDB: add-symbol-file %s%s.gdb 0x%p -s .data 0x%p -s .bss 0x%p\\n\", GDB_PATH, fno->fname, reloc_text, reloc_data, reloc_bss);\n\n    vfsi->type = VFS_TYPE_BFLT;\n    vfsi->allocated = reloc_data;\n    vfsi->init = init;\n\n    return (void*)vfsi;\n}\n\nstatic int xipfs_unlink(struct fnode *fno)\n{\n    return -1; /* Cannot unlink */\n}\n\nstatic int xip_add(const char *name, const void (*init), uint32_t size)\n{\n    struct xipfs_fnode *xip = kalloc(sizeof(struct xipfs_fnode));\n    if (!xip)\n        return -1;\n    xip->fnode = fno_create(&mod_xipfs, name, fno_search(\"/bin\"));\n    if (!xip->fnode) {\n        kfree(xip);\n        return -1;\n    }\n    xip->fnode->priv = xip;\n\n    /* Make executable */\n    xip->fnode->flags |= FL_EXEC;\n    xip->fnode->size = size;\n    xip->init = init;\n    return 0;\n}\n\nstatic int xipfs_parse_blob(const uint8_t *blob)\n{\n    const struct xipfs_fat *fat = (const struct xipfs_fat *)blob;\n    const struct xipfs_fhdr *f;\n    int i, offset;\n    if (!fat)\n        return -1;\n\n    offset = sizeof(struct xipfs_fat);\n    for (i = 0; i < fat->fs_files; i++) {\n        f = (const struct xipfs_fhdr *) (blob + offset);\n        if ((f->magic != XIPFS_MAGIC) && (f->magic != XIPFS_MAGIC_ICELINK))\n            return -1;\n        if (f->magic == XIPFS_MAGIC) {\n            xip_add(f->name, f->payload, f->len);\n            offset += f->len + sizeof(struct xipfs_fhdr);\n        } else {\n            char fullname[64] = \"/bin/\";\n            strcpy(fullname + 5, f->name);\n            vfs_symlink(\"/bin/icebox\", fullname);\n            offset += sizeof(struct xipfs_fhdr);\n        }\n        while ((offset % 4) != 0)\n            offset++;\n    }\n    return 0;\n}\n\nstatic int xipfs_mount(char *source, char *tgt, uint32_t flags, void *arg)\n{\n    struct fnode *tgt_dir = NULL;\n    /* Source must NOT be NULL */\n    if (!source)\n        return -1;\n\n    /* Target must be a valid dir */\n    if (!tgt)\n        return -1;\n\n    tgt_dir = fno_search(tgt);\n\n    if (!tgt_dir || ((tgt_dir->flags & FL_DIR) == 0)) {\n        /* Not a valid mountpoint. */\n        return -1;\n    }\n\n    tgt_dir->owner = &mod_xipfs;\n    if (xipfs_parse_blob((uint8_t *)source) < 0)\n        return -1;\n\n    return 0;\n}\n\n\nvoid xipfs_init(void)\n{\n    mod_xipfs.family = FAMILY_FILE;\n    mod_xipfs.mount = xipfs_mount;\n    strcpy(mod_xipfs.name,\"xipfs\");\n    mod_xipfs.ops.read = xipfs_read;\n    mod_xipfs.ops.poll = xipfs_poll;\n    mod_xipfs.ops.write = xipfs_write;\n    mod_xipfs.ops.seek = xipfs_seek;\n    mod_xipfs.ops.creat = xipfs_creat;\n    mod_xipfs.ops.unlink = xipfs_unlink;\n    mod_xipfs.ops.close = xipfs_close;\n    mod_xipfs.ops.exe = xipfs_exe;\n\n    mod_xipfs.ops.block_read = xipfs_block_read;\n    register_module(&mod_xipfs);\n}\n"
  },
  {
    "path": "kernel/fs/xipfs.h",
    "content": "#ifndef XIPFS_INCLUDED\n#define XIPFS_INCLUDED\n#define XIPFS_MAGIC 0xC519FF55\n\n#include <stdint.h>\n\nstruct xipfs_fat {\n    uint32_t fs_magic;\n    uint32_t fs_size;\n    uint32_t fs_files;\n    uint32_t timestamp;\n};\n\nstruct xipfs_fhdr {\n    uint32_t magic;\n    char  name[56];\n    uint32_t len;\n    uint8_t  payload[0];\n};\n\nvoid xipfs_init(void);\n#endif\n"
  },
  {
    "path": "kernel/getaddrinfo.c",
    "content": "/*  \n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as \n *      published by the Free Software Foundation.\n *      \n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */  \n#include \"frosted.h\"\n#include \"drivers/socket_in.h\"\n\n#ifndef CONFIG_DNS_CLIENT\nint sys_getaddrinfo_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4)\n{\n    return -ENOSYS;\n}\n\nint sys_freeaddrinfo_hdlr(uint32_t arg1)\n{\n    return -ENOSYS;\n}\n#else\n\n\n\n#define DNSQUERY_IDLE           0\n#define DNSQUERY_OK             1\n#define DNSQUERY_IN_PROGRESS    2\n#define DNSQUERY_FAIL           0xFF\n\nstruct dnsquery_cookie\n{\n    char            *node;\n    struct addrinfo *res;\n    struct task     *task;\n    uint8_t         state;\n};\n\nstruct waiting_task {\n    struct task *task;\n    struct waiting_task *next;\n};\n\n\nstatic uint16_t get_port(char *service)\n{\n    int i;\n    int f = 1;\n    uint16_t p = 0;\n    if (!service)\n        return 0;\n    for (i = strlen(service) - 1; i >= 0; i--) {\n        if (service[i] < '0' || service[i] > '9')\n            return 0;\n        p += (service[i] - '0') * f;\n        f *= 10;\n    }\n    return p;\n}\n\n\n\n\nstatic struct dnsquery_cookie ck4 = { NULL, 0, DNSQUERY_IDLE };\nstatic struct dnsquery_cookie ck6 = { NULL, 0, DNSQUERY_IDLE };\nstatic struct waiting_task *waiting_list = NULL;\n\n\nstatic int dns_is_busy(void)\n{\n    if (ck4.state == DNSQUERY_IN_PROGRESS)\n        return 1;\n#ifdef CONFIG_IPV6\n    if (ck6.state == DNSQUERY_IN_PROGRESS)\n        return 1;\n#endif\n    return 0;\n}\n\nstatic int add_to_waiting_list(void)\n{\n    struct waiting_task *wt = kalloc(sizeof(struct waiting_task));\n    if (!wt)\n        return -1;\n    wt->next = waiting_list;\n    wt->task = this_task();\n    return 0;\n}\n\n#ifdef CONFIG_IPV6\nstatic void dns_ip6_cb(char *ip, void *arg)\n{\n    if (ip) {\n        new = u_calloc(1, sizeof(struct addrinfo));\n        if (!new) {\n            ck6.state= DNSQUERY_FAIL;\n            task_resume(ck6.task);\n            return;\n        }\n        new->ai_family = AF_INET6;\n        new->ai_addr = u_calloc(1, sizeof(struct sockaddr_in6));\n        if (!new->ai_addr) {\n            f_free(new);\n            ck6.state = DNSQUERY_FAIL;\n            task_resume(ck6.task);\n            return;\n        }\n        new->ai_addrlen = sizeof(struct sockaddr_in6);\n        pico_string_to_ipv6(ip, (((struct sockaddr_in6*)(new->ai_addr))->sin6_addr.s6_addr)); \n        ((struct sockaddr_in6*)(new->ai_addr))->sin6_family = AF_INET6;\n        new->ai_next = ck6.res;\n        ck6.res = new;\n        ck6.state = DNSQUERY_OK;\n    } else {\n        /* No ip given, but still callback was called: timeout! */\n        ck6.state = DNSQUERY_FAIL;\n    }\n    task_resume(ck6.task);\n}\n#endif\n\nstatic void dns_ip4_cb(char *ip, void *arg)\n{\n    struct addrinfo *new;\n    if (ip) {\n        new = u_calloc(1, sizeof(struct addrinfo));\n        if (!new) {\n            ck4.state = DNSQUERY_FAIL;\n            task_resume(ck4.task);\n            return;\n        }\n        new->ai_family = AF_INET;\n        new->ai_addr = u_calloc(1, sizeof(struct sockaddr_in));\n        if (!new->ai_addr) {\n            f_free(new);\n            ck4.state = DNSQUERY_FAIL;\n            task_resume(ck4.task);\n            return;\n        }\n        new->ai_addrlen = sizeof(struct sockaddr_in);\n        pico_string_to_ipv4(ip, &(((struct sockaddr_in*)new->ai_addr)->sin_addr.s_addr));    \n        ((struct sockaddr_in*)(new->ai_addr))->sin_family = AF_INET;\n        new->ai_next = ck4.res;\n        ck4.res = new;\n        ck4.state = DNSQUERY_OK;\n    } else {\n        /* No ip given, but still callback was called: timeout! */\n        ck4.state = DNSQUERY_FAIL;\n    }\n    task_resume(ck4.task);\n}\n\nstatic void dns_idle(void)\n{\n    struct waiting_task *wt;\n    ck6.state = DNSQUERY_IDLE;\n    ck4.state = DNSQUERY_IDLE;\n\n    while(waiting_list) {\n        wt = waiting_list;\n        task_resume(wt->task);\n        waiting_list = wt->next;\n        kfree(wt);\n    }\n}\n\nstatic int pico_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)\n{\n    struct sockaddr_in sa4;\n    struct sockaddr_in6 sa6;\n    (void)service;\n\n    /* If an IP address was passed in the string, resolve immediately */\n#ifdef CONFIG_IPV6\n    if (pico_string_to_ipv6(node, sa6.sin6_addr.s6_addr) == 0) {\n        struct addrinfo *ai = u_calloc(1, sizeof(struct addrinfo));\n        if (!ai)\n            return -ENOMEM;\n        ai->ai_family = AF_INET6;\n        ai->ai_addr = u_calloc(1, sizeof(struct sockaddr_in6));\n        ai->ai_addrlen = sizeof(struct sockaddr_in6);\n        ai->ai_next = NULL;\n        sa6.sin6_family = AF_INET6;\n        sa6.sin6_port = short_be(get_port(service));\n        memcpy(ai->ai_addr, &sa6, sizeof(struct sockaddr_in6));\n        *res = ai;\n        return 0;\n    }\n#endif\n\n    if (pico_string_to_ipv4(node, &sa4.sin_addr.s_addr) == 0) {\n        struct addrinfo *ai = u_calloc(1, sizeof(struct addrinfo));\n        if (!ai)\n            return -ENOMEM;\n        ai->ai_family = AF_INET;\n        ai->ai_addr = u_calloc(1, sizeof(struct sockaddr_in));\n        ai->ai_addrlen = sizeof(struct sockaddr_in);\n        ai->ai_next = NULL;\n        sa4.sin_family = AF_INET;\n        sa4.sin_port = short_be(get_port(service));\n        memcpy(ai->ai_addr, &sa4, sizeof(struct sockaddr_in));\n        *res = ai;\n        return 0;\n    }\n\n    /* If an operation is in progress, block until it's over */ \n    if (dns_is_busy()) {\n        if (add_to_waiting_list() < 0)\n            return -ENOMEM;\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n\n    /* Check if it's the resumed call, and the address has been resolved. */\n#ifdef CONFIG_IPV6 \n    if ((ck6.state == DNSQUERY_OK) && (ck6.node == node)) {\n        *res = ck6.res;\n        dns_idle();\n        return 0;\n    }\n    \n    if ((ck6.state == DNSQUERY_FAIL) && (ck4.node == node)) {\n        dns_idle();\n        return 0 - pico_err;\n    }\n#endif\n\n    if ((ck4.state == DNSQUERY_OK) && (ck4.node == node)) {\n        *res = ck4.res;\n        dns_idle();\n        return 0;\n    }\n\n    if ((ck4.state == DNSQUERY_FAIL) && (ck4.node == node)) {\n        dns_idle();\n        return 0 - pico_err;\n    }\n\n#ifdef CONFIG_IPV6\n    if (!hints || (hints->ai_family == AF_INET6)) {\n        ck6.state = DNSQUERY_IN_PROGRESS; \n        ck6.node = node;\n        ck6.res = NULL;\n        ck6.task = this_task();\n        if (pico_dns_client_getaddr6(node, dns_ip6_cb, NULL) < 0) {\n            dns_idle();\n            return 0 - pico_err;\n        }\n    }\n#endif\n\n    if (!hints || (hints->ai_family == AF_INET)) {\n        ck4.state = DNSQUERY_IN_PROGRESS; \n        ck4.node = node;\n        ck4.res = NULL;\n        ck4.task = this_task();\n        if (pico_dns_client_getaddr(node, dns_ip4_cb, NULL) < 0) {\n            dns_idle();\n            return 0 - pico_err;\n        }\n    }\n    task_suspend();\n    return SYS_CALL_AGAIN;\n}\n\nstatic int pico_freeaddrinfo(struct addrinfo *res)\n{\n    struct addrinfo *cur = res;\n    struct addrinfo *nxt;\n    while(cur) {\n        if (cur->ai_addr)\n            f_free(cur->ai_addr);\n        nxt = cur->ai_next;\n        f_free(cur);\n        cur = nxt;\n    }\n    return 0;\n}\n\n\nint sys_getaddrinfo_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4)\n{\n    if (task_ptr_valid(arg1) || task_ptr_valid(arg2) || task_ptr_valid(arg3) || task_ptr_valid(arg4))\n        return -EACCES;\n    return pico_getaddrinfo((const char *)arg1, (const char *)arg2, (struct addrinfo *)arg3, (struct addrinfo **)arg4);\n}\n\nint sys_freeaddrinfo_hdlr(uint32_t arg1)\n{\n    if (task_ptr_valid(arg1))\n        return -EACCES;\n    return pico_freeaddrinfo((struct addrinfo *)arg1);\n}\n\n#endif\n"
  },
  {
    "path": "kernel/hardfault_debug.c",
    "content": "/**\r\n * HardFault_HandlerAsm:\r\n * Alternative Hard Fault handler to help debug the reason for a fault.\r\n * To use, edit the vector table to reference this function in the HardFault vector\r\n * This code is suitable for Cortex-M3 and Cortex-M0 cores\r\n */\r\n\r\nvoid HardFault_HandlerC(unsigned long *hardfault_args);\r\n\r\n// Use the 'naked' attribute so that C stacking is not used.\r\n__attribute__((naked))\r\nvoid HardFault_Handler(void)\r\n{\r\n    /*\r\n     * Get the appropriate stack pointer, depending on our mode,\r\n     * and use it as the parameter to the C handler. This function\r\n     * will never return\r\n     */\r\n    __asm(\"TST LR, #4           \\n\"\r\n          \"ITE EQ               \\n\"\r\n          \"MRSEQ R0, MSP        \\n\"\r\n          \"MRSNE R0, PSP        \\n\"\r\n          \"B HardFault_HandlerC \\n\"\r\n           );\r\n}\r\n\r\n// Use the 'naked' attribute so that C stacking is not used.\r\n__attribute__((naked))\r\nvoid UsageFault_Handler(void)\r\n{\r\n    /*\r\n     * Get the appropriate stack pointer, depending on our mode,\r\n     * and use it as the parameter to the C handler. This function\r\n     * will never return\r\n     */\r\n    __asm(\"TST LR, #4           \\n\"\r\n          \"ITE EQ               \\n\"\r\n          \"MRSEQ R0, MSP        \\n\"\r\n          \"MRSNE R0, PSP        \\n\"\r\n          \"B HardFault_HandlerC \\n\"\r\n           );\r\n}\r\n\r\n/**\r\n * HardFaultHandler_C:\r\n * This is called from the HardFault_HandlerAsm with a pointer the Fault stack\r\n * as the parameter. We can then read the values from the stack and place them\r\n * into local variables for ease of reading.\r\n * We then read the various Fault Status and Address Registers to help decode\r\n * cause of the fault.\r\n * The function ends with a BKPT instruction to force control back into the debugger\r\n */\r\nvolatile unsigned long stacked_r0 ;\r\nvolatile unsigned long stacked_r1 ;\r\nvolatile unsigned long stacked_r2 ;\r\nvolatile unsigned long stacked_r3 ;\r\nvolatile unsigned long stacked_r12 ;\r\nvolatile unsigned long stacked_lr ;\r\nvolatile unsigned long stacked_pc ;\r\nvolatile unsigned long stacked_psr ;\r\nvolatile unsigned long _CFSR ;\r\nvolatile unsigned long _HFSR ;\r\nvolatile unsigned long _DFSR ;\r\nvolatile unsigned long _AFSR ;\r\nvolatile unsigned long _BFAR ;\r\nvolatile unsigned long _MMAR ;\r\n\r\nvoid HardFault_HandlerC(unsigned long *hardfault_args){\r\n    stacked_r0 = ((unsigned long)hardfault_args[0]) ;\r\n    stacked_r1 = ((unsigned long)hardfault_args[1]) ;\r\n    stacked_r2 = ((unsigned long)hardfault_args[2]) ;\r\n    stacked_r3 = ((unsigned long)hardfault_args[3]) ;\r\n    stacked_r12 = ((unsigned long)hardfault_args[4]) ;\r\n    stacked_lr = ((unsigned long)hardfault_args[5]) ;\r\n    stacked_pc = ((unsigned long)hardfault_args[6]) ;\r\n    stacked_psr = ((unsigned long)hardfault_args[7]) ;\r\n\r\n        // Configurable Fault Status Register\r\n        // Consists of MMSR, BFSR and UFSR\r\n    _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ;   \r\n                                            \r\n    // Hard Fault Status Register\r\n    _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ;\r\n\r\n    // Debug Fault Status Register\r\n    _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ;\r\n\r\n    // Auxiliary Fault Status Register\r\n    _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ;\r\n\r\n    // Read the Fault Address Registers. These may not contain valid values.\r\n    // Check BFARVALID/MMARVALID to see if they are valid values\r\n    // MemManage Fault Address Register\r\n    _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ;\r\n    // Bus Fault Address Register\r\n    _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ;\r\n\r\n    __asm(\"BKPT #0\") ; // Break into the debugger\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "kernel/heap.h",
    "content": "\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define DECLARE_HEAP(type, orderby)                                                     \\\nstruct heap_element_##type {                                                            \\\n    uint32_t id;                                                                        \\\n    type data;                                                                          \\\n};                                                                                      \\\nstruct heap_##type {                                                                    \\\n    uint32_t size;                                                                      \\\n    uint32_t n;                                                                         \\\n    uint32_t last_id;                                                                   \\\n    struct heap_element_##type *top;                                                    \\\n};                                                                                      \\\ntypedef struct heap_##type heap_##type;                                                 \\\nstatic uint32_t _heap_idx_count = 0;                                                    \\\nstatic inline int heap_insert(struct heap_##type *heap, type *el)                       \\\n{                                                                                       \\\n    int i;                                                                              \\\n    struct heap_element_##type etmp;                                                    \\\n    memcpy(&etmp.data, el, sizeof(type));                                               \\\n    if (++heap->n >= heap->size) {                                                      \\\n        heap->top = krealloc(heap->top,                                                 \\\n                (heap->n + 1) * sizeof(struct heap_element_##type));                    \\\n        if (!heap->top) {                                                               \\\n            heap->n--;                                                                  \\\n            return -1;                                                                  \\\n        }                                                                               \\\n        heap->size++;                                                                   \\\n    }                                                                                   \\\n    etmp.id = heap->last_id++;                                                          \\\n    if ((heap->last_id & 0x80000000U) != 0)                                             \\\n       heap->last_id = 0; /* Wrap around */                                             \\\n    if (heap->n == 1) {                                                                 \\\n        memcpy(&heap->top[1], &etmp, sizeof(struct heap_element_##type));               \\\n        return (int)etmp.id;                                                            \\\n    }                                                                                   \\\n    for (i = heap->n; ((i > 1) &&                                                       \\\n                (heap->top[i / 2].data.orderby > el->orderby)); i /= 2) {               \\\n        memcpy(&heap->top[i], &heap->top[i / 2], sizeof(struct heap_element_##type));   \\\n    }                                                                                   \\\n    memcpy(&heap->top[i], &etmp, sizeof(struct heap_element_##type));                   \\\n    return (int)etmp.id;                                                                \\\n} \\\nstatic inline int heap_peek(struct heap_##type *heap, type *first)                      \\\n{                                                                                       \\\n    type *ptr = NULL;                                                                   \\\n    struct heap_element_##type *last;                                                   \\\n    int i, child, ret;                                                                  \\\n    if(heap->n == 0) {                                                                  \\\n        return -1;                                                                      \\\n    }                                                                                   \\\n    memcpy(first, &heap->top[1].data, sizeof(type));                                    \\\n    last = &heap->top[heap->n--];                                                       \\\n    for(i = 1; (i * 2) <= heap->n; i = child) {                                         \\\n        child = 2 * i;                                                                  \\\n        if ((child != heap->n) &&                                                       \\\n            (heap->top[child + 1]).data.orderby                                         \\\n            < (heap->top[child]).data.orderby)                                          \\\n            child++;                                                                    \\\n        if (last->data.orderby >                                                        \\\n            heap->top[child].data.orderby)                                              \\\n            memcpy(&heap->top[i], &heap->top[child],                                    \\\n                    sizeof(struct heap_element_##type));                                \\\n        else                                                                            \\\n            break;                                                                      \\\n    }                                                                                   \\\n    memcpy(&heap->top[i], last, sizeof(struct heap_element_##type));                    \\\n    return 0;                                                                           \\\n} \\\nstatic inline int heap_delete(struct heap_##type *heap, int id)                         \\\n{                                                                                       \\\n    int found = 0;                                                                      \\\n    int i, child;                                                                       \\\n    struct heap_element_##type *last, temp;                                             \\\n    if (heap->n == 0) {                                                                 \\\n        return -1;                                                                      \\\n    }                                                                                   \\\n    for (i = 1; i <= heap->n; i++) {                                                    \\\n        if (heap->top[i].id == id) {                                                    \\\n                found = i;                                                              \\\n                break;                                                                  \\\n        }                                                                               \\\n    }                                                                                   \\\n    if (!found) {                                                                       \\\n        return -1;                                                                      \\\n    }                                                                                   \\\n    if (found == 1) {                                                                   \\\n        (void)heap_peek(heap, &temp.data);                                              \\\n        return 0;                                                                       \\\n    }                                                                                   \\\n    if (found == heap->n) {                                                             \\\n        heap->n--;                                                                      \\\n        return 0;                                                                       \\\n    }                                                                                   \\\n    last = &heap->top[heap->n--];                                                       \\\n    memcpy(&heap->top[found], last, sizeof(struct heap_element_##type));                \\\n    for(i = found; i < heap->n; i++) {                                                  \\\n        if (heap->top[i].data.orderby > heap->top[i + 1].data.orderby) {                \\\n            memcpy(&temp, &heap->top[i], sizeof(struct heap_element_##type));           \\\n            memcpy(&heap->top[i], &heap->top[i+1], sizeof(struct heap_element_##type)); \\\n            memcpy(&heap->top[i+1], &temp, sizeof(struct heap_element_##type));         \\\n        }                                                                               \\\n    }                                                                                   \\\n    return 0;                                                                           \\\n} \\\nstatic inline type *heap_first(heap_##type *heap)                                       \\\n{                                                                                       \\\n    if (heap->n == 0)                                                                   \\\n        return NULL;                                                                    \\\n    return &heap->top[1].data;                                                          \\\n} \\\nstatic inline heap_##type *heap_init(void)                                              \\\n{                                                                                       \\\n    heap_##type *p = kcalloc(1, sizeof(heap_##type));                                    \\\n    return p;                                                                           \\\n} \\\nstatic inline void heap_destroy(heap_##type *h)                                         \\\n{                                                                                       \\\n    kfree(h->top);                                                                      \\\n    kfree(h);                                                                           \\\n}\n\n"
  },
  {
    "path": "kernel/interrupts.h",
    "content": "\n#ifndef FROSTED_INTERRUPTS_H\n#define FROSTED_INTERRUPTS_H\n\nextern void __set_BASEPRI(int);\n\n#ifdef DEBUG\n    static void irq_off(void)\n    {\n    }\n    \n    static void irq_on(void)\n    {\n    }\n\n    static void irq_setmask(void)\n    {\n    }\n    \n    static void irq_clearmask(void)\n    {\n    }\n#else\n    /* Inline kernel utils */\n\n    static inline void irq_setmask(void)\n    {\n        __set_BASEPRI(3);\n    }\n    \n    static inline void irq_clearmask(void)\n    {\n        __set_BASEPRI(0u);\n    }\n\n    static inline void irq_off(void)\n    {\n        asm volatile (\"cpsid i                \\n\");\n    }\n    \n    static inline void irq_on(void)\n    {\n        asm volatile (\"cpsie i                \\n\");\n    }\n#endif\n\n#endif /* FROSTED_INTERRUPTS_H */\n"
  },
  {
    "path": "kernel/kprintf.c",
    "content": "/*\n *  frosted - printf() library function\n *\n Based on Georges Menie's printf -\n Copyright 2001, 2002 Georges Menie (www.menie.org)\n stdarg version contributed by Christian Ettinger\n Originally released under LGPL2+.\n\n This program is free software; you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License version 2, as\n published by the Free Software Foundation.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program; if not, write to the Free Software\n Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n */\n\n#include <stdint.h>\n#include <string.h>\n#include <sys/vfs.h>\n#include \"frosted.h\"\n#include \"errno.h\"\n#include \"cirbuf.h\"\n#include \"poll.h\"\n#include \"device.h\"\n#include <stdarg.h>\n\n#ifdef CONFIG_KLOG\nstruct dev_klog {\n    struct fnode *fno;\n    struct cirbuf *buf;\n\tint used;\n    struct task *task;\n};\n\nstatic struct dev_klog klog;\n\n\nstatic int klog_open(const char *path, int flags)\n{\n    if (klog.used)\n        return -EBUSY;\n    klog.used++;\n    return task_filedesc_add(fno_search(\"/dev/klog\"));\n}\n\nstatic int klog_close(struct fnode *f)\n{\n    (void)f;\n    klog.used = 0;\n    return 0;\n}\n\nstatic int klog_read(struct fnode *fno, void *buf, unsigned int len)\n{\n    int ret;\n    if (len == 0)\n        return len;\n    if (!buf)\n        return -EINVAL;\n\n    ret = cirbuf_readbytes(klog.buf, buf, len);\n    if (ret <= 0) {\n        klog.task = this_task();\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n    return ret;\n}\n\nstatic int klog_poll(struct fnode *fno, uint16_t events, uint16_t *revents)\n{\n    if (events != POLLIN)\n        return 0;\n    if (cirbuf_bytesinuse(klog.buf) > 0) {\n        *revents = POLLIN;\n        return 1;\n    }\n    return 0;\n}\n\nstatic struct module mod_klog = {\n    .family = FAMILY_DEV,\n    .name = \"klog\",\n    .ops.open = klog_open,\n    .ops.read = klog_read,\n    .ops.poll = klog_poll,\n    .ops.close = klog_close\n};\n\n\n\nstatic void printchar(char **str, int c)\n{\n    if (str) {\n        **str = c;\n        ++(*str);\n    }\n    else {\n        if (cirbuf_bytesfree(klog.buf)) {\n            cirbuf_writebyte(klog.buf, c);\n            if (klog.task != NULL) \n                task_resume(klog.task);\n        }\n    }\n}\n\n#define PAD_RIGHT 1\n#define PAD_ZERO 2\n\nstatic int prints(char **out, const char *string, int width, int pad)\n{\n    int pc = 0, padchar = ' ';\n\n    if (width > 0) {\n        int len = 0;\n        const char *ptr;\n        for (ptr = string; *ptr; ++ptr) ++len;\n        if (len >= width) width = 0;\n        else width -= len;\n        if (pad & PAD_ZERO) padchar = '0';\n    }\n    if (!(pad & PAD_RIGHT)) {\n        for ( ; width > 0; --width) {\n            printchar (out, padchar);\n            ++pc;\n        }\n    }\n    for ( ; *string ; ++string) {\n        printchar (out, *string);\n        ++pc;\n    }\n    for ( ; width > 0; --width) {\n        printchar (out, padchar);\n        ++pc;\n    }\n\n    return pc;\n}\n\n/* the following should be enough for 32 bit int */\n#define PRINT_BUF_LEN 12\n\nstatic int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)\n{\n    char print_buf[PRINT_BUF_LEN];\n    char *s;\n    int t, neg = 0, pc = 0;\n    unsigned int u = i;\n\n    if (i == 0) {\n        print_buf[0] = '0';\n        print_buf[1] = '\\0';\n        return prints (out, print_buf, width, pad);\n    }\n\n    if (sg && b == 10 && i < 0) {\n        neg = 1;\n        u = -i;\n    }\n\n    s = print_buf + PRINT_BUF_LEN-1;\n    *s = '\\0';\n\n    while (u) {\n        t = u % b;\n        if( t >= 10 )\n            t += letbase - '0' - 10;\n        *--s = t + '0';\n        u /= b;\n    }\n\n    if (neg) {\n        if( width && (pad & PAD_ZERO) ) {\n            printchar (out, '-');\n            ++pc;\n            --width;\n        }\n        else {\n            *--s = '-';\n        }\n    }\n\n    return pc + prints (out, s, width, pad);\n}\n\nstatic int print(char **out, const char *format, va_list args )\n{\n    int width, pad;\n    int pc = 0;\n    char scr[2];\n\n    for (; *format != 0; ++format) {\n        if (*format == '%') {\n            ++format;\n            width = pad = 0;\n            if (*format == '\\0') break;\n            if (*format == '%') goto out;\n            if (*format == '-') {\n                ++format;\n                pad = PAD_RIGHT;\n            }\n\n            while ((*format == 'h') || (*format == 'l'))\n                ++format;\n\n            while (*format == '0') {\n                ++format;\n                pad |= PAD_ZERO;\n            }\n            for ( ; *format >= '0' && *format <= '9'; ++format) {\n                width *= 10;\n                width += *format - '0';\n            }\n            if( *format == 's' ) {\n                register char *s = (char *)va_arg( args, int );\n                pc += prints (out, s?s:\"(null)\", width, pad);\n                continue;\n            }\n            if( *format == 'd' ) {\n                pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');\n                continue;\n            }\n            if( *format == 'x' || *format == 'p') {\n                pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');\n                continue;\n            }\n            if( *format == 'X' ) {\n                pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');\n                continue;\n            }\n            if( *format == 'u' ) {\n                pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');\n                continue;\n            }\n            if( *format == 'c' ) {\n                scr[0] = (char)va_arg( args, int );\n                scr[1] = '\\0';\n                pc += prints(out, scr, width, pad);\n                continue;\n            }\n        }\n        else {\nout:\n            printchar (out, *format);\n            ++pc;\n        }\n    }\n    if (out) **out = '\\0';\n    va_end( args );\n    return pc;\n}\n\nstatic mutex_t *klog_lock;\n\nint kprintf(const char *format, ...)\n{\n    va_list args;\n    int ret;\n    if (cirbuf_bytesfree(klog.buf)) {\n        if (mutex_trylock(klog_lock) < 0)\n            return 0;\n        va_start(args, format);\n        ret = print(0, format, args);\n        mutex_unlock(klog_lock);\n        return ret;\n    }\n    return 0;\n}\n\nint ksprintf(char *out, const char *format, ...)\n{\n    va_list args;\n    va_start( args, format );\n    return print( &out, format, args );\n}\n\nint klog_init(void)\n{\n    klog.fno = fno_create_rdonly(&mod_klog, \"klog\", fno_search(\"/dev\"));\n    if (klog.fno == NULL) {\n        return -1;\n    }\n    klog.buf = cirbuf_create(CONFIG_KLOG_SIZE);\n\tklog.used = 0;\n    klog.task = NULL;\n    klog_lock = mutex_init();\n    return 0;\n}\n#endif\n"
  },
  {
    "path": "kernel/kprintf.h",
    "content": "#ifndef KPRINTF_H\n#define KPRINTF_H\n\n#ifdef CONFIG_KLOG\nint klog_init(void);\nint ksprintf(char *out, const char *format, ...);\nint kprintf(const char *format, ...);\n#else\n#   define klog_init() (0)\n#   define kprintf\n#endif\n\n\n#endif\n"
  },
  {
    "path": "kernel/lm3s/Kconfig",
    "content": "if ARCH_LM3S\n\nchoice \n    prompt \"MCU\"\n    default LM3S6965\nconfig ARCH_LM3S6965\n    bool \"LM3S6965\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_64KB\nconfig ARCH_LM3SVIRT\n    bool \"LM3S-VIRTUAL\"\n    select FLASH_SIZE_1MB\n    select RAM_SIZE_256KB\nendchoice\n\nendif\n"
  },
  {
    "path": "kernel/lm3s/lm3s.c",
    "content": ""
  },
  {
    "path": "kernel/lm3s/lm3s.ld.in",
    "content": "/******************************************************************************\n *\n * standalone.ld - Linker script for applications using startup.c \n *\n *****************************************************************************/\nENTRY(reset_handler) \nMEMORY\n{\n    FLASH (rx) : ORIGIN = __FLASH_ORIGIN, LENGTH = __KFLASHMEM_SIZE\n    SRAM (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __KRAMMEM_SIZE\n    SRAM_USER (rwx) : ORIGIN = (__RAM1_BASE + __KRAMMEM_SIZE), LENGTH = (__RAM1_SIZE - __KRAMMEM_SIZE)\n}\n\n__StackTop = ORIGIN(SRAM) + LENGTH(SRAM) - 4;\n \nSECTIONS\n{\n    .text :\n    {\n        KEEP(*(.vectors))\n        *(.text*)\n        *(.rodata*)\n    } > FLASH\n\t/* C++ Static constructors/destructors, also used for __attribute__\n\t * ((constructor)) and the likes */\n\t.preinit_array : {\n\t\t. = ALIGN(4);\n\t\t__preinit_array_start = .;\n\t\tKEEP (*(.preinit_array))\n\t\t__preinit_array_end = .;\n\t} > FLASH\n\t.init_array : {\n\t\t. = ALIGN(4);\n\t\t__init_array_start = .;\n\t\tKEEP (*(SORT(.init_array.*)))\n\t\tKEEP (*(.init_array))\n\t\t__init_array_end = .;\n\t} > FLASH\n\t.fini_array : {\n\t\t. = ALIGN(4);\n\t\t__fini_array_start = .;\n\t\tKEEP (*(.fini_array))\n\t\tKEEP (*(SORT(.fini_array.*)))\n\t\t__fini_array_end = .;\n\t} > FLASH\n \n    .data :\n    {\n        _etext = LOADADDR(.data);\n        _data = .;\n        *(vtable)\n        *(.data*)\n        _edata = .;\n    } > SRAM AT > FLASH\n\t_data_loadaddr = LOADADDR(.data);\n \n    .bss :\n    {\n        _bss = .;\n        *(.bss*)\n        *(COMMON)\n        . = ALIGN(32 / 8);\n        _ebss = .;\n        PROVIDE (end = .);\n    } > SRAM\n\n    .heap :\n    {\n        /* heap starts after BSS */\n        PROVIDE(_heap_start = _ebss );\n    } > SRAM\n}\n\nPROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));\nPROVIDE(_user_heap_start = ORIGIN(SRAM_USER));\nPROVIDE(_user_heap_end = ORIGIN(SRAM_USER) + LENGTH(SRAM_USER));\n\n"
  },
  {
    "path": "kernel/lm3s/lm3s6965evb.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/lm3s/usart.h\"\n#include \"unicore-mx/lm3s/nvic.h\"\n#include \"eth.h\"\n\n#ifdef CONFIG_DEVUART\n#include \"uart.h\"\n#endif\n\n/* TODO: Move to unicore-mx when implemented */\nint exti_init(void)\n{\n    return 0;\n}\n\nint exti_enable(void)\n{\n    return 0;\n}\n\nint exti_register(void)\n{\n    return 0;\n}\n\nint gpio_init(void)\n{\n    return 0;\n}\n\nint gpio_create(struct module *mod, const struct gpio_config *gpio_config)\n{\n    return 0;\n}\n\n\nvoid usart_set_baudrate(uint32_t usart, uint32_t baud)\n{\n    /* TODO */\n    (void)usart;\n    (void)baud;\n}\n\nvoid usart_set_databits(uint32_t usart, int bits)\n{\n    /* TODO */\n    (void)usart;\n    (void)bits;\n}\n\nvoid usart_set_stopbits(uint32_t usart, enum usart_stopbits sb)\n{\n    /* TODO */\n    (void)usart;\n    (void)sb;\n}\n\nvoid usart_set_parity(uint32_t usart, enum usart_parity par)\n{\n    /* TODO */\n    (void)usart;\n    (void)par;\n}\n\nvoid usart_set_mode(uint32_t usart, enum usart_mode mode)\n{\n    /* TODO */\n    (void)usart;\n    (void)mode;\n}\n\nvoid usart_set_flow_control(uint32_t usart, enum usart_flowcontrol fc)\n{\n    /* TODO */\n    (void)usart;\n    (void)fc;\n}\n\nvoid usart_enable(uint32_t usart)\n{\n       (void)usart;\n}\n\nvoid usart_disable(uint32_t usart)\n{\n       (void)usart;\n}\n\n\n\n static const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_0\n         {\n             .base = USART0_BASE,\n             .irq = NVIC_UART0_IRQ,\n         },\n#endif\n#ifdef CONFIG_USART_1\n         {\n             .base = USART1_BASE,\n             .irq = NVIC_UART1_IRQ,\n         },\n#endif\n#ifdef CONFIG_USART_2\n         {\n             .base = USART2_BASE,\n             .irq = NVIC_UART2_IRQ,\n         },\n#endif\n };\n\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\n\nint machine_init(void)\n{\n    int i;\n    rcc_clock_setup_in_xtal_8mhz_out_50mhz();\n\n    for (i = 0; i < NUM_UARTS; i++)\n        uart_create(&(uart_configs[i]));\n\n    ethernet_init(NULL);\n\n    return 0;\n}\n\n\n"
  },
  {
    "path": "kernel/locks.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent, brabo\n *\n */\n#include \"frosted.h\"\n#include \"locks.h\"\n#include <sys/time.h>\n\n#define SIGN_MUTEX (0xCAFEC0C0)\n#define SIGN_SEMAP (0xCAFECAFE)\n\n\nextern int _mutex_lock(void *);\nextern int _mutex_unlock(void *);\nextern int _sem_wait(void *);\nextern int _sem_post(void *);\n\n/* Semaphore: internal functions */\nstatic void _add_listener(sem_t *s)\n{\n    int i;\n    struct task *t = this_task();\n\n    if (s->last >= 0) {\n        if (t == s->listener[s->last])\n            return;\n    }\n\n    for (i = s->last + 1; i < s->listeners; i++) {\n        if (s->listener[i] == NULL) {\n            s->listener[i] = t;\n            s->last = i;\n            return;\n        }\n    }\n    for (i = 0; i < s->last; i++) {\n        if (s->listener[i] == NULL) {\n            s->listener[i] = t;\n            s->last = i;\n            return;\n        }\n    }\n}\n\nstatic void _del_listener(sem_t *s)\n{\n    int i;\n    struct task *t = this_task();\n    for (i = 0; i < s->listeners; i++) {\n        if (s->listener[i] == t) {\n            s->listener[i] = NULL;\n            return;\n        }\n    }\n}\n\nstatic int sem_spinwait(sem_t *s)\n{\n    if (!s)\n        return -EINVAL;\n    while (_sem_wait(s) != 0) {\n        /* spin ... */\n    }\n    return 0;\n}\n\n/* Semaphore: API */\n\nint sem_trywait(sem_t *s)\n{\n    if (!s)\n        return -EINVAL;\n    if(_sem_wait(s) != 0)\n        return -EAGAIN;\n    return 0;\n}\n\nint sem_wait(sem_t *s, struct timespec *timeout)\n{\n    if (this_task() == NULL)\n        return sem_spinwait(s);\n    if (!s)\n        return -EINVAL;\n    if(_sem_wait(s) != 0) {\n        if (timeout) {\n            long time_left = (timeout->tv_sec * 1000) + (timeout->tv_nsec / 1000 / 1000) - jiffies;\n            if ((time_left > 0) && (task_get_timer_id() < 0)) {\n                task_set_timer_id(ktimer_add(time_left, sleepy_task_wakeup, NULL));\n            } else {\n                if (time_left < 0) {\n                    return -ETIMEDOUT;\n                }\n                return SYS_CALL_AGAIN;\n            }\n        }\n        _add_listener(s);\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n    _del_listener(s);\n    return 0;\n}\n\nint sem_post(sem_t *s)\n{\n    if (!s)\n        return -EINVAL;\n    if (_sem_post(s) > 0) {\n        int i;\n        for(i = s->last+1; i < s->listeners; i++) {\n            struct task *t = s->listener[i];\n            if (t) {\n                task_resume_lock(t);\n                s->listener[i] = NULL;\n            }\n        }\n        for(i = 0; i <= s->last; i++) {\n            struct task *t = s->listener[i];\n            if (t) {\n                task_resume_lock(t);\n                s->listener[i] = NULL;\n            }\n        }\n    }\n    return 0;\n}\n\nint sem_destroy(sem_t *sem)\n{\n    if (sem->listener)\n        kfree(sem->listener);\n    kfree(sem);\n    return 0;\n}\n\nint sem_init(sem_t *s, int val)\n{\n    int i;\n    s->signature = SIGN_SEMAP;\n    s->value = val;\n    s->listeners = 8;\n    s->last = -1;\n    s->listener = kalloc(sizeof(struct task *) * (s->listeners + 1));\n    for (i = 0; i < s->listeners; i++)\n        s->listener[i] = NULL;\n\n    return 0;\n}\n\n/* Semaphore: Syscalls */\nint sys_sem_init_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    if (task_ptr_valid((sem_t *)arg1)) {\n        return -EACCES;\n    }\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s)\n        return -EACCES;\n    return sem_init((sem_t *)arg1, arg2);\n}\n\nint sys_sem_post_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s || s->signature != SIGN_SEMAP)\n        return -EACCES;\n    return sem_post((sem_t *)arg1);\n}\n\nint sys_sem_wait_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s || s->signature != SIGN_SEMAP)\n        return -EACCES;\n    return sem_wait((sem_t *)arg1, (struct timespec *)arg2);\n}\n\nint sys_sem_trywait_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s || s->signature != SIGN_SEMAP)\n        return -EACCES;\n    return sem_trywait((sem_t *)arg1);\n}\n\nint sys_sem_destroy_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s || s->signature != SIGN_SEMAP)\n        return -EACCES;\n    return sem_destroy((sem_t *)arg1);\n}\n\nint suspend_on_sem_wait(sem_t *s)\n{\n    int ret;\n    if (!s)\n        return -EINVAL;\n    ret = _sem_wait(s);\n    if (ret != 0) {\n        _add_listener(s);\n        return EAGAIN;\n    }\n    return 0;\n}\n\n/* Mutex: API */\nmutex_t *mutex_init()\n{\n    mutex_t *s = kalloc(sizeof(mutex_t));\n    if (s) {\n        int i;\n        s->signature = SIGN_MUTEX;\n        s->value = 1; /* Unlocked. */\n        s->listeners = 8;\n        s->last = -1;\n        s->listener = kalloc(sizeof(struct task *) * (s->listeners + 1));\n        for (i = 0; i < s->listeners; i++)\n            s->listener[i] = NULL;\n    }\n    return s;\n}\n\nvoid mutex_destroy(mutex_t *s)\n{\n    if (s->listener)\n        kfree(s->listener);\n    kfree(s);\n}\n\nstatic int mutex_spinlock(mutex_t *s)\n{\n    if (!s)\n        return -EINVAL;\n    while (_mutex_lock(s) != 0) {\n        /* spin... */\n    }\n    return 0;\n}\n\nint mutex_trylock(mutex_t *s)\n{\n    if (!s)\n        return -EINVAL;\n    if(_mutex_lock(s) != 0)\n        return -EAGAIN;\n    return 0;\n}\n\nint mutex_lock(mutex_t *s)\n{\n    if (this_task() == NULL)\n        return mutex_spinlock(s);\n    if (!s)\n        return -EINVAL;\n    if(_mutex_lock(s) != 0) {\n        _add_listener(s);\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n    _del_listener(s);\n    return 0;\n}\n\nint mutex_unlock(mutex_t *s)\n{\n    if (!s)\n        return -EINVAL;\n    if (_mutex_unlock(s) == 0) {\n        int i;\n        for(i = s->last+1; i < s->listeners; i++) {\n            struct task *t = s->listener[i];\n            if (t) {\n                task_resume_lock(t);\n                s->listener[i] = NULL;\n                return 0;\n            }\n        }\n        for(i = 0; i <= s->last; i++) {\n            struct task *t = s->listener[i];\n            if (t) {\n                task_resume_lock(t);\n                s->listener[i] = NULL;\n                return 0;\n            }\n        }\n        return 0;\n    }\n    return -EAGAIN;\n}\n\nint suspend_on_mutex_lock(mutex_t *s)\n{\n    int ret;\n    if (!s)\n        return -EINVAL;\n    ret = _mutex_lock(s);\n    if (ret != 0) {\n        _add_listener(s);\n        return EAGAIN;\n    }\n    return 0;\n}\n\n\n/* Mutex: Syscalls */\nint sys_mutex_init_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return (int)mutex_init(arg1);\n}\n\nint sys_mutex_lock_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s || s->signature != SIGN_MUTEX)\n        return -EACCES;\n    return mutex_lock((mutex_t *)arg1);\n}\n\nint sys_mutex_unlock_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s || s->signature != SIGN_MUTEX)\n        return -EACCES;\n    return mutex_unlock((mutex_t *)arg1);\n}\n\nint sys_mutex_destroy_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct semaphore *s = (struct semaphore *)arg1;\n    if (!s || s->signature != SIGN_MUTEX)\n        return -EACCES;\n    return sem_destroy((sem_t *)arg1); /* Same as semaphore */\n}\n\n"
  },
  {
    "path": "kernel/locks.h",
    "content": "#include \"frosted.h\"\n/* Structures */\nstruct semaphore {\n    int value;\n    uint32_t signature;\n    int listeners;\n    int last;\n    struct task **listener;\n};\n\n\nint suspend_on_sem_wait(sem_t *s);\nint suspend_on_mutex_lock(mutex_t *s);\n"
  },
  {
    "path": "kernel/lowpower.h",
    "content": "#ifndef LOWPOWER_H_INC\n#define LOWPOWER_H_INC\n#include <stdint.h>\n\n#ifndef CONFIG_LOWPOWER\n#   define lowpower_init() (-1)\n#   define lowpower_sleep(x,y) (-1)\n#else\n    int lowpower_init(void);\n    int lowpower_sleep(int stdby, uint32_t interval);\n#endif\n#endif\n"
  },
  {
    "path": "kernel/lpc17xx/Kconfig",
    "content": "if ARCH_LPC17XX\n\nchoice \n    prompt \"MCU\"\n    default ARCH_LPC1768\nconfig ARCH_LPC1763\n    bool \"LPC1763\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_32KB\n    select CLK_100MHZ\nconfig ARCH_LPC1764\n    bool \"LPC1764\"\n    select FLASH_SIZE_128KB\n    select RAM_SIZE_16KB\n    select CLK_100MHZ\nconfig ARCH_LPC1765\n    bool \"LPC1765\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_32KB\n    select CLK_100MHZ\nconfig ARCH_LPC1766\n    bool \"LPC1766\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_32KB\n    select CLK_100MHZ\nconfig ARCH_LPC1767\n    bool \"LPC1767\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_32KB\n    select CLK_100MHZ\nconfig ARCH_LPC1768\n    bool \"LPC1768\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_32KB\n    select CLK_100MHZ\nconfig ARCH_LPC1769\n    bool \"LPC1769\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_32KB\nendchoice\n\nendif\n"
  },
  {
    "path": "kernel/lpc17xx/lpc1768mbed.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/lpc17xx/clock.h>\n#include <unicore-mx/lpc17xx/nvic.h>\n#include <unicore-mx/lpc17xx/pwr.h>\n#include <unicore-mx/lpc17xx/uart.h>\n#include <unicore-mx/lpc17xx/gpio.h>\n#include \"gpio.h\"\n#include \"uart.h\"\n\n\n#if CONFIG_SYS_CLOCK == 100000000\n    const uint32_t clock_96MHZ = CLOCK_96MHZ;\n#else\n#error No valid clock speed selected for lpc1768mbed\n#endif\n\nstatic const struct gpio_config Leds[] = {\n    {.base=GPIO1, .pin=GPIOPIN18, .mode=GPIO_MODE_OUTPUT, .name=\"led0\", /* .exti=1, .trigger=EXTI_TRIGGER_RISING */},\n    {.base=GPIO1, .pin=GPIOPIN20, .mode=GPIO_MODE_OUTPUT, .name=\"led1\", /* .exti=1, .trigger=EXTI_TRIGGER_RISING */},\n    {.base=GPIO1, .pin=GPIOPIN21, .mode=GPIO_MODE_OUTPUT, .name=\"led2\", /* .exti=1, .trigger=EXTI_TRIGGER_RISING */},\n    {.base=GPIO1, .pin=GPIOPIN23, .mode=GPIO_MODE_OUTPUT, .name=\"led3\", /* .exti=1, .trigger=EXTI_TRIGGER_RISING */},\n};\n#define NUM_LEDS (sizeof(Leds) / sizeof(struct gpio_config))\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_0\n    {\n        .devidx = 0,\n        .base = UART0_BASE,\n        .irq = NVIC_UART0_IRQ,\n        .rcc = PWR_PCONP_UART0,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO0, .pin=GPIOPIN3,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO0, .pin=GPIOPIN2,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .name=NULL,},\n\n    },\n#endif\n#ifdef CONFIG_USART_1\n    {\n        .devidx = 1,\n        .base = UART1_BASE,\n        .irq = NVIC_UART1_IRQ,\n        .rcc = PWR_PCONP_UART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO2, .pin=GPIOPIN1,.mode=GPIO_MODE_AF,.af=GPIO_AF2, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO2, .pin=GPIOPIN0,.mode=GPIO_MODE_AF,.af=GPIO_AF2, .name=NULL,},\n\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = UART2_BASE,\n        .irq = NVIC_UART2_IRQ,\n        .rcc = PWR_PCONP_UART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO0, .pin=GPIOPIN11,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO0, .pin=GPIOPIN10,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .name=NULL,},\n    },\n#endif\n#ifdef CONFIG_USART_3\n    {\n        .devidx = 3,\n        .base = UART3_BASE,\n        .irq = NVIC_UART3_IRQ,\n        .rcc = PWR_PCONP_UART3,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO0, .pin=GPIOPIN26,.mode=GPIO_MODE_AF,.af=GPIO_AF3, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO0, .pin=GPIOPIN25,.mode=GPIO_MODE_AF,.af=GPIO_AF3, .name=NULL,},\n    },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\n/* TODO: Move to unicore-mx when implemented */\n\nvoid usart_set_baudrate(uint32_t usart, uint32_t baud)\n{\n    /* TODO */\n    (void)usart;\n    (void)baud;\n}\n\nvoid usart_set_databits(uint32_t usart, int bits)\n{\n    /* TODO */\n    (void)usart;\n    (void)bits;\n}\n\nvoid usart_set_stopbits(uint32_t usart, enum usart_stopbits sb)\n{\n    /* TODO */\n    (void)usart;\n    (void)sb;\n}\n\nvoid usart_set_parity(uint32_t usart, enum usart_parity par)\n{\n    /* TODO */\n    (void)usart;\n    (void)par;\n}\n\nvoid usart_set_mode(uint32_t usart, enum usart_mode mode)\n{\n    /* TODO */\n    (void)usart;\n    (void)mode;\n}\n\nvoid usart_set_flow_control(uint32_t usart, enum usart_flowcontrol fc)\n{\n    /* TODO */\n    (void)usart;\n    (void)fc;\n}\n\n\n/* TODO: Move to unicore-mx when implemented */\nint exti_init(void)\n{\n    return 0;\n}\n\nint exti_enable(void)\n{\n    return 0;\n}\n\nint exti_register(void)\n{\n    return 0;\n}\n\nvoid usart_enable(uint32_t usart)\n{\n       (void)usart;\n}\n\nvoid usart_disable(uint32_t usart)\n{\n       (void)usart;\n}\n\n\nint machine_init(void)\n{\n    int i;\n    clock_setup(&clock_scale[clock_96MHZ]);\n\n    /* Leds */\n    for (i = 0; i < 4; i++) {\n        gpio_create(NULL, &Leds[i]);\n    }\n\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n    return 0;\n\n}\n\n"
  },
  {
    "path": "kernel/lpc17xx/lpc1769xpresso.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/lpc17xx/clock.h>\n#include <unicore-mx/lpc17xx/nvic.h>\n#include <unicore-mx/lpc17xx/pwr.h>\n#include <unicore-mx/lpc17xx/uart.h>\n#include <unicore-mx/lpc17xx/gpio.h>\n#include \"gpio.h\"\n#include \"uart.h\"\n\nstatic const struct gpio_config Leds[] = {\n    {.base=GPIO0, .pin=GPIOPIN22, .mode=GPIO_MODE_OUTPUT, .name=\"led0\" },\n};\n#define NUM_LEDS (sizeof(Leds) / sizeof(struct gpio_config))\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_0\n    {\n        .devidx = 0,\n        .base = UART0_BASE,\n        .irq = NVIC_UART0_IRQ,\n        .rcc = PWR_PCONP_UART0,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO0, .pin=GPIOPIN3,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO0, .pin=GPIOPIN2,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .name=NULL,},\n\n    },\n#endif\n#ifdef CONFIG_USART_1\n    {\n        .devidx = 1,\n        .base = UART1_BASE,\n        .irq = NVIC_UART1_IRQ,\n        .rcc = PWR_PCONP_UART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO0, .pin=GPIOPIN16,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO0, .pin=GPIOPIN15,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .name=NULL,},\n\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = UART2_BASE,\n        .irq = NVIC_UART2_IRQ,\n        .rcc = PWR_PCONP_UART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO0, .pin=GPIOPIN11,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO0, .pin=GPIOPIN10,.mode=GPIO_MODE_AF,.af=GPIO_AF1, .name=NULL,},\n    },\n#endif\n#ifdef CONFIG_USART_3\n    {\n        .devidx = 3,\n        .base = UART3_BASE,\n        .irq = NVIC_UART3_IRQ,\n        .rcc = PWR_PCONP_UART3,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {.base=GPIO0, .pin=GPIOPIN1,.mode=GPIO_MODE_AF,.af=GPIO_AF2, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n        .pio_tx = {.base=GPIO0, .pin=GPIOPIN0,.mode=GPIO_MODE_AF,.af=GPIO_AF2, .name=NULL,},\n    },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\n/* TODO: Move to unicore-mx when implemented */\n\nvoid usart_set_baudrate(uint32_t usart, uint32_t baud)\n{\n    /* TODO */\n    (void)usart;\n    (void)baud;\n}\n\nvoid usart_set_databits(uint32_t usart, int bits)\n{\n    /* TODO */\n    (void)usart;\n    (void)bits;\n}\n\nvoid usart_set_stopbits(uint32_t usart, enum usart_stopbits sb)\n{\n    /* TODO */\n    (void)usart;\n    (void)sb;\n}\n\nvoid usart_set_parity(uint32_t usart, enum usart_parity par)\n{\n    /* TODO */\n    (void)usart;\n    (void)par;\n}\n\nvoid usart_set_mode(uint32_t usart, enum usart_mode mode)\n{\n    /* TODO */\n    (void)usart;\n    (void)mode;\n}\n\nvoid usart_set_flow_control(uint32_t usart, enum usart_flowcontrol fc)\n{\n    /* TODO */\n    (void)usart;\n    (void)fc;\n}\n\n\n/* TODO: Move to unicore-mx when implemented */\nint exti_init(void)\n{\n    return 0;\n}\n\nint exti_enable(void)\n{\n    return 0;\n}\n\nint exti_register(void)\n{\n    return 0;\n}\n\nvoid usart_enable(uint32_t usart)\n{\n       (void)usart;\n}\n\nvoid usart_disable(uint32_t usart)\n{\n       (void)usart;\n}\n\n\nint machine_init(void)\n{\n    int i;\n    clock_setup(&clock_scale[CLOCK_120MHZ]);\n\n    /* Leds */\n    gpio_create(NULL, &Leds[0]);\n\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "kernel/lpc17xx/lpc17xx.ld.in",
    "content": "MEMORY\r\n{\r\n    FLASH (rx) : ORIGIN = __FLASH_ORIGIN, LENGTH = __KFLASHMEM_SIZE\r\n    SRAM (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __KRAMMEM_SIZE\r\n    SRAM_USER (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE\r\n    SRAM_EXTRA(rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE\r\n}\r\n\r\n /* Enforce emmition of the vector table. */\r\nEXTERN (vector_table)\r\n\r\n/* Define the entry point of the output file. */\r\nENTRY(reset_handler)\r\n \r\nSECTIONS\r\n{\r\n    .text :\r\n    {\r\n        KEEP(*(.vectors))\r\n        *(.text*)\r\n        *(.rodata*)\r\n    } > FLASH\r\n\t/* C++ Static constructors/destructors, also used for __attribute__\r\n\t * ((constructor)) and the likes */\r\n\t.preinit_array : {\r\n\t\t. = ALIGN(4);\r\n\t\t__preinit_array_start = .;\r\n\t\tKEEP (*(.preinit_array))\r\n\t\t__preinit_array_end = .;\r\n\t} > FLASH\r\n\t.init_array : {\r\n\t\t. = ALIGN(4);\r\n\t\t__init_array_start = .;\r\n\t\tKEEP (*(SORT(.init_array.*)))\r\n\t\tKEEP (*(.init_array))\r\n\t\t__init_array_end = .;\r\n\t} > FLASH\r\n\t.fini_array : {\r\n\t\t. = ALIGN(4);\r\n\t\t__fini_array_start = .;\r\n\t\tKEEP (*(.fini_array))\r\n\t\tKEEP (*(SORT(.fini_array.*)))\r\n\t\t__fini_array_end = .;\r\n\t} > FLASH\r\n\r\n    .data :\r\n    {\r\n        _etext = LOADADDR(.data);\r\n        _data = .;\r\n        *(vtable)\r\n        *(.data*)\r\n        _edata = .;\r\n    } > SRAM AT > FLASH\r\n\t_data_loadaddr = LOADADDR(.data);\r\n\r\n    .bss :\r\n    {\r\n        _bss = .;\r\n        *(.bss*)\r\n        *(COMMON)\r\n        . = ALIGN(32 / 8);\r\n        _ebss = .;\r\n        PROVIDE (end = .);\r\n    } > SRAM\r\n\r\n    .heap :\r\n    {\r\n        /* heap starts after BSS */\r\n        PROVIDE(_heap_start = _ebss );\r\n    } > SRAM\r\n}\r\n\r\nPROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));\r\nPROVIDE(_user_heap_start = ORIGIN(SRAM_USER));\r\nPROVIDE(_user_heap_end = ORIGIN(SRAM_USER) + LENGTH(SRAM_USER));\r\nPROVIDE(_extra_heap_start = ORIGIN(SRAM_EXTRA));\r\nPROVIDE(_extra_heap_end = ORIGIN(SRAM_EXTRA) + LENGTH(SRAM_EXTRA));\r\n\r\n"
  },
  {
    "path": "kernel/lpc17xx.h",
    "content": "#ifndef INC_LPC17CC\n#define INC_LPC17CC\n\n#ifdef CONFIG_DEVUART\n#include \"uart.h\"\n#endif\n\n#ifdef CONFIG_DEVUART\nvoid uart_init(struct fnode * dev, const struct uart_addr uart_addrs[], int num_uarts);\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/malloc.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include <stdint.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"malloc.h\"\n#include \"scheduler.h\"\n#include \"frosted.h\"\n#include \"locks.h\"\n\n/*------------------*/\n/* Defines          */\n/*------------------*/\n#define F_MALLOC_MAGIC    (0xDECEA5ED)\n\n\n#if defined __linux__ || defined _WIN32 /* test application */\n#define dbg_malloc printf\n#else\n#define dbg_malloc(...) do{}while(0)\n#endif\n\n#define F_IN_USE 0x20\n#define in_use(x) (((x->flags) & F_IN_USE) == F_IN_USE)\n#define block_valid(b) ((b) && (b->magic == F_MALLOC_MAGIC))\nstatic void blk_rearrange(void *arg);\n\nstatic inline int MEMPOOL(int x)\n{\n#ifdef CONFIG_TCPIP_MEMPOOL\n    if (x == MEM_TCPIP)\n        return 3;\n#endif\n    if (x == MEM_EXTRA)\n        return 4;\n    if (x == MEM_TASK)\n        return 2;\n    if (x == MEM_USER)\n        return 1;\n    return 0;\n}\n\n/*------------------*/\n/* Structures       */\n/*------------------*/\nstruct f_malloc_block {\n    uint32_t magic;                 /* magic fingerprint */\n    struct f_malloc_block * prev;   /* previous block */\n    struct f_malloc_block * next;   /* next, or last block? */\n    size_t size;                    /* malloc size excluding this block - next block is adjacent, if !last_block */\n    uint32_t flags;\n    int pid;\n};\n\n\n/*------------------*/\n/* Local variables  */\n/*------------------*/\nstatic struct f_malloc_block *malloc_entry[5] = {NULL, NULL, NULL, NULL, NULL};\n\n/* Globals */\nstruct f_malloc_stats f_malloc_stats[5] = {};\n\n/* Mlock is a special lock, so initialization is made static */\nstatic struct task *_m_listeners[16] = {};\nstatic struct semaphore _mlock = { .signature = 0xCAFEC0C0, .value = 1, .listeners=16, .last=-1, .listener=_m_listeners};\nstatic mutex_t * const mlock = (mutex_t *)(&_mlock);\n\n#define KMEM_SIZE   (CONFIG_KRAM_SIZE << 10)\n\n/*------------------*/\n/* Local functions  */\n/*------------------*/\n\n/* merges two blocks\n *  returns: pointer to the merged block\n */\nstatic struct f_malloc_block * merge_blocks(struct f_malloc_block * first, struct f_malloc_block * second)\n{\n    struct f_malloc_block *temp;\n    if (first > second) {\n        temp = first;\n        first = second;\n        second = temp;\n    }\n    /* new size = sum of sizes + overhead */\n    first->size = first->size + sizeof(struct f_malloc_block) + second->size;\n    /* first block's next pointer should now point the second blocks next pointer */\n    first->next = second->next;\n    /* third block's prev pointer should now point to the first block, instead of the second */\n    if (second->next)\n        second->next->prev = first;\n    return first;\n}\n\n/* split a block in two.\n * blk: block to be split\n * size: size of the first block\n * return: NULL on failure, otherwise pointer to the new free block (second block)\n * NOTE: the second block will be put in the free-blocks pool, with the remaining size\n */\nstatic struct f_malloc_block * split_block(struct f_malloc_block * blk, size_t size)\n{\n    size_t free_size;\n    struct f_malloc_block * free_blk;\n\n    /* does it fit? */\n    if ((blk->size - sizeof(struct f_malloc_block)) <= size)\n        return NULL;\n\n    /* shrink the block to requested size */\n    free_size = blk->size - sizeof(struct f_malloc_block) - size;\n    blk->size = size;\n    /* create new block */\n    free_blk = (struct f_malloc_block *)(((uint8_t *)blk) + sizeof(struct f_malloc_block) + blk->size);\n    free_blk->prev = blk;\n    free_blk->next = blk->next;\n    blk->next = free_blk;\n    free_blk->magic = F_MALLOC_MAGIC;\n    free_blk->size = free_size;\n    free_blk->flags = 0u;\n    return free_blk;\n}\n\nstatic int block_fits(struct f_malloc_block *blk, size_t size, int flags)\n{\n    uint32_t baddr = (uint32_t)blk;\n    uint32_t reqsize = size + sizeof(struct f_malloc_block);\n    if (!blk)\n        return 0;\n\n    if (!block_valid(blk))\n        return 0;\n\n    if (in_use(blk))\n        return 0;\n\n    if (size > blk->size)\n        return 0;\n\n    return 1;\n}\n\nstatic struct f_malloc_block * f_find_best_fit(int flags, size_t size, struct f_malloc_block ** last)\n{\n    struct f_malloc_block *found = NULL, *blk = malloc_entry[MEMPOOL(flags)];\n\n    /* See if we can find a free block that fits */\n    while (blk) /* last entry will break the loop */\n    {\n        *last = blk; /* last travelled node */\n\n        if (block_fits(blk, size, flags))\n        {\n            /* found a fit - is it better than a possible previously found block? */\n            if ((!found) || (blk->size < found->size))\n                found = blk;\n        }\n        if ((blk->next) && (!block_valid(blk->next)))\n            blk->next = NULL;\n\n        /* travel next block */\n        blk = blk->next;\n    }\n    return found;\n}\n\nstatic unsigned char * heap_end_kernel;\nstatic unsigned char * heap_stack;\nstatic unsigned char * heap_end_user;\nstatic unsigned char * heap_end_extra;\n\nstatic unsigned char * heap_limit_user;\nstatic unsigned char * heap_limit_kernel;\nstatic unsigned char * heap_limit_extra;\n\n#ifdef CONFIG_TCPIP_MEMPOOL\n    static char * heap_end_tcpip = (char *)CONFIG_TCPIP_MEMPOOL;\n#else\n    static char * heap_end_tcpip = NULL;\n#endif\n\nstatic void * f_sbrk(int flags, int incr)\n{\n    extern char   end;              /* Set by linker */\n    extern char   _stack;           /* Set by linker */\n    extern char   _user_heap_start; /* Set by linker */\n    extern char   _user_heap_end;   /* Set by linker */\n#ifdef CONFIG_SDRAM\n    extern char   _external_heap_start; /* Set by linker */\n    extern char   _external_heap_end;   /* Set by linker */\n#endif\n#ifdef CONFIG_SRAM_EXTRA\n    extern char   _extra_heap_start; /* Set by linker */\n    extern char   _extra_heap_end;   /* Set by linker */\n#endif\n    const char  * heap_stack_high = &_stack;\n    char        * prev_heap_end;\n\n    /* Set initial heap addresses */\n    if (heap_end_kernel == 0) {\n        /* kernel memory */\n        heap_end_kernel = &end;\n        heap_limit_kernel = &end + KMEM_SIZE;\n\n#ifdef CONFIG_SRAM_EXTRA\n        /* extra memory */\n        heap_end_extra = &_extra_heap_start;\n        heap_limit_extra = &_extra_heap_end;\n#endif\n#ifdef CONFIG_SDRAM\n        /* user memory  = external ram*/\n        heap_end_user = &_external_heap_start; /* Start at beginning of heap */\n        heap_limit_user = &_external_heap_end;\n#else\n        /* user memory */\n        heap_end_user = &_user_heap_start; /* Start at beginning of heap */\n        heap_limit_user = &_user_heap_end;\n#endif\n\n        /* task/stack memory */\n        heap_stack = &_stack - CONFIG_TASK_STACK_SIZE;\n    }\n\n    int mem_pool = MEMPOOL(flags);\n    if (mem_pool == MEMPOOL(MEM_USER)) {\n      if (!heap_end_user)\n        return (void *)(0 - 1);\n      /* Do not over-commit */\n      if ((heap_end_user + incr) >= heap_limit_user)\n        return (void *)(0 - 1);\n      prev_heap_end = heap_end_user;\n      heap_end_user += incr;\n      memset(prev_heap_end, 0, incr);\n    } else if (mem_pool == MEMPOOL(MEM_TASK)) {\n      if ((heap_stack - incr) < heap_end_kernel)\n        return (void *)(0 - 1);\n      heap_stack -= incr;\n      prev_heap_end = heap_stack;\n#ifdef CONFIG_SRAM_EXTRA\n    } else if (mem_pool == MEMPOOL(MEM_EXTRA)) {\n      if (!heap_end_extra)\n        return (void *)(0 - 1);\n      /* Do not over-commit */\n      if ((heap_end_extra + incr) >= heap_limit_extra)\n        return (void *)(0 - 1);\n      prev_heap_end = heap_end_extra;\n      heap_end_extra += incr;\n      memset(prev_heap_end, 0, incr);\n#endif\n#ifdef CONFIG_TCPIP_MEMPOOL\n    } else if (mem_pool == MEMPOOL(MEM_TCPIP)) {\n      if (!heap_end_tcpip)\n        return (void *)(0 - 1);\n      prev_heap_end = heap_end_tcpip;\n      heap_end_tcpip += incr;\n#endif\n    } else {\n      if (((heap_end_kernel + incr) >= heap_limit_kernel) ||\n          ((heap_end_kernel + incr) > heap_stack))\n        return (void*)(0 - 1);\n      prev_heap_end = heap_end_kernel;\n      heap_end_kernel += incr;\n    }\n    return (void *) prev_heap_end;\n}\n\nstatic void f_compact(struct f_malloc_block *blk)\n{\n    if (!blk->prev)\n        return;\n    blk->prev->next = NULL;\n    int mem_pool = MEMPOOL(blk->flags);\n    if (mem_pool == MEMPOOL(MEM_USER)) {\n        heap_end_user -= (blk->size + sizeof(struct f_malloc_block));\n    } else if (mem_pool == MEMPOOL(MEM_EXTRA)) {\n        heap_end_extra -= (blk->size + sizeof(struct f_malloc_block));\n    } else if (mem_pool == MEMPOOL(MEM_TASK)) {\n        heap_stack += (blk->size + sizeof(struct f_malloc_block));\n#ifdef CONFIG_TCPIP_MEMPOOL\n    } else if (mem_pool == MEMPOOL(MEM_TCPIP)) {\n        heap_end_tcpip -= (blk->size + sizeof(struct f_malloc_block));\n#endif\n    } else {\n        heap_end_kernel -= (blk->size + sizeof(struct f_malloc_block));\n    }\n}\n\n/*------------------*/\n/* Public functions */\n/*------------------*/\nvoid * f_calloc(int flags, size_t num, size_t size)\n{\n    void * ptr = f_malloc(flags, num * size);\n    if (ptr)\n        memset(ptr, 0, num * size);\n    return ptr;\n}\n\nvoid * u_calloc(size_t num, size_t size)\n{\n    void *addr;\n    addr = f_calloc(MEM_USER, num, size);\n#ifdef CONFIG_SRAM_EXTRA\n    if (!addr)\n        addr = f_calloc(MEM_EXTRA, num, size);\n#endif\n    return addr;\n}\n\nvoid * f_realloc(int flags, void* ptr, size_t size)\n{\n    void * out = NULL;\n    struct f_malloc_block * blk = NULL;\n\n    /* size zero and valid ptr -> act as regular free() */\n    if (!size && ptr)\n        goto realloc_free;\n\n    if (ptr)\n        blk = (struct f_malloc_block *)(((uint8_t*)ptr) - sizeof(struct f_malloc_block));\n\n    if (!ptr)\n    {\n        /* f ptr is not valid, act as regular malloc() */\n        out = f_malloc(flags, size);\n    }\n    else if (blk && block_valid(blk))\n    {\n        size_t new_size, copy_size;\n        if (!in_use(blk)) {\n            task_segfault((uint32_t)ptr, 0, MEMFAULT_ACCESS);\n        }\n\n        /* If requested size is the same as current, do nothing. */\n        if (blk->size == size)\n            return ptr;\n        else if (size > blk->size)\n        {\n            /* Grow to requested size by copying the content */\n            new_size = size;\n            copy_size = blk->size;\n        } else {\n            /* Shrink  (Ignore for now) */\n            return ptr;\n        }\n        out = f_malloc(flags, new_size);\n        if (!out)  {\n            return NULL;\n        }\n        memcpy(out, ptr, copy_size);\n    }\n\nrealloc_free:\n    if (ptr) {\n        struct f_malloc_block * blk;\n        blk = (struct f_malloc_block *)((uint8_t *)ptr - sizeof(struct f_malloc_block));\n        f_free(ptr);\n        blk_rearrange(blk);\n    }\n    return out;\n}\n\nvoid *u_realloc(void *ptr, size_t size)\n{\n    void *addr;\n    addr = f_realloc(MEM_USER, ptr, size);\n#ifdef CONFIG_SRAM_EXTRA\n    if (!addr)\n        addr = f_realloc(MEM_EXTRA, ptr, size);\n#endif\n    return addr;\n}\n\nstatic void f_proc_heap_free_pool(int pid, int mempool)\n{\n    struct f_malloc_block *blk = malloc_entry[MEMPOOL(mempool)];\n    while (blk) {\n        if (!block_valid(blk))\n            while(1); /* corrupt block! */\n        if ((blk->pid == pid) && in_use(blk)) {\n            f_free(blk);\n            blk_rearrange(blk);\n        }\n        blk = blk->next;\n    }\n}\n\nvoid f_proc_heap_free(int pid)\n{\n    f_proc_heap_free_pool(pid, MEM_USER);\n    f_proc_heap_free_pool(pid, MEM_EXTRA);\n}\n\nuint32_t f_proc_heap_count_pool(int pid, int mempool)\n{\n    struct f_malloc_block *blk = malloc_entry[MEMPOOL(mempool)];\n    uint32_t size = 0;\n    while (blk)\n        {\n            if ((blk->pid == pid) && in_use(blk)) {\n                size += blk->size;\n            }\n            blk = blk->next;\n        }\n    return size;\n}\n\nuint32_t f_proc_heap_count(int pid)\n{\n    uint32_t size = f_proc_heap_count_pool(pid, MEM_USER);\n    size += f_proc_heap_count_pool(pid, MEM_EXTRA);\n    return size;\n}\n\nvoid * u_malloc(size_t size)\n{\n    void *addr;\n    addr = f_malloc(MEM_USER, size);\n#ifdef CONFIG_SRAM_EXTRA\n    if (!addr)\n        addr = f_malloc(MEM_EXTRA, size);\n#endif\n    return addr;\n}\n\nvoid * f_malloc(int flags, size_t size)\n{\n    struct f_malloc_block * blk = NULL, *last = NULL;\n    void *ret = NULL;\n    while((size % 4) != 0) {\n        size++;\n    }\n\n    /* kernelspace calls: pid=0 (kernel, kthreads */\n    if (this_task_getpid() == 0) {\n\n        /* kernel receives a null (no blocking) */\n        if (this_task() == NULL) {\n            if (mutex_trylock(mlock) < 0)\n                return NULL;\n        } else {\n            /* ktrheads can block. */\n            mutex_lock(mlock);\n        }\n    }\n    /* Userspace calls acquire mlock in the syscall handler. */\n\n\n    /* Travel the linked list for first fit */\n    blk = f_find_best_fit(flags, size, &last);\n    if (blk)\n    {\n        dbg_malloc(\"Found best fit!\\n\");\n        /*\n         * if ((flags & MEM_USER) && blk->next && ((uint8_t *)blk + 24 + blk->size != (uint8_t *)blk->next))\n         *      while(1);;\n         */\n        /* first fit found, now split it if it's much bigger than needed */\n        if (2 * (size + sizeof(struct f_malloc_block)) < blk->size)\n        {\n            dbg_malloc(\"Splitting blocks, since requested size [%d] << best fit block size [%d]!\\n\", size, blk->size);\n            split_block(blk, size);\n        }\n    } else {\n        /* No first fit found: ask for new memory */\n        blk = (struct f_malloc_block *)f_sbrk(flags, size + sizeof(struct f_malloc_block));  // can OS give us more memory?\n        if ((long)blk == -1) {\n            ret = NULL;\n            goto out;\n        }\n\n        /* first call -> set entrypoint */\n        if (malloc_entry[MEMPOOL(flags)] == NULL) {\n            malloc_entry[MEMPOOL(flags)] = blk;\n            blk->prev = NULL;\n        }\n        blk->magic = F_MALLOC_MAGIC;\n        blk->size = size;\n        blk->next = NULL; /* Newly allocated memory is always last in the linked list */\n        /* Link this entry to the previous last entry */\n        if (last)\n        {\n            // assert(last->next == NULL);\n            last->next = blk;\n        }\n        blk->prev = last;\n    }\n\n    /* destination found, fill in  meta-data */\n    blk->flags = F_IN_USE | flags;\n    if (flags & MEM_USER)\n        blk->pid = this_task_getpid();\n    else\n        blk->pid = 0;\n\n    /* update stats */\n    f_malloc_stats[MEMPOOL(flags)].malloc_calls++;\n    f_malloc_stats[MEMPOOL(flags)].objects_allocated++;\n    f_malloc_stats[MEMPOOL(flags)].mem_allocated += ((uint32_t)blk->size + sizeof(struct f_malloc_block));\n\n    ret = (void *)(((uint8_t *)blk) + sizeof(struct f_malloc_block)); // pointer to newly allocated mem\n\nout:\n    /* Userspace calls release mlock in the syscall handler. */\n    if (this_task_getpid() == 0) {\n        mutex_unlock(mlock);\n    }\n    if (ret && (flags & MEM_TASK)) {\n        memset(ret, 0x55, size);\n    }\n    return ret;\n}\n\nstatic void blk_rearrange(void *arg)\n{\n    struct f_malloc_block *blk = arg;\n\n\n    /* Merge adjecent free blocks (consecutive blocks are always adjacent) */\n    if ((blk->prev) && (!in_use(blk->prev)))\n    {\n        blk = merge_blocks(blk->prev, blk);\n    }\n    if ((blk->next) && (!in_use(blk->next)))\n    {\n        blk = merge_blocks(blk, blk->next);\n    }\n    if (!blk->next)\n        f_compact(blk);\n}\n\n\nvoid f_free(void * ptr)\n{\n    struct f_malloc_block * blk;\n    int pid = this_task_getpid();\n    blk = (struct f_malloc_block *)((uint8_t *)ptr - sizeof(struct f_malloc_block));\n\n    if (!ptr) {\n        return;\n    }\n    if (block_valid(blk))\n    {\n        if (!in_use(blk)) {\n            task_segfault((uint32_t)ptr, 0, MEMFAULT_DOUBLEFREE);\n        }\n        blk->flags &= ~F_IN_USE;\n        /* stats */\n        f_malloc_stats[MEMPOOL(blk->flags)].free_calls++;\n        f_malloc_stats[MEMPOOL(blk->flags)].objects_allocated--;\n        f_malloc_stats[MEMPOOL(blk->flags)].mem_allocated -= (uint32_t)blk->size + sizeof(struct f_malloc_block);\n    } else {\n        dbg_malloc(\"FREE ERR: %p is not a valid allocated pointer!\\n\", blk);\n    }\n}\n\n/* Some statistic helpers */\n\nuint32_t mem_stats_frag(int pool)\n{\n    uint32_t frag_size = 0u;\n    struct f_malloc_block *blk;\n\n    mutex_lock(mlock);\n    blk = malloc_entry[pool];\n    while (blk) {\n        if (!in_use(blk))\n            frag_size += blk->size + sizeof(struct f_malloc_block);\n        blk = blk->next;\n    }\n    mutex_unlock(mlock);\n    return frag_size;\n}\n\nstatic int fmalloc_check_block_owner(int pool, const uint8_t *ptr)\n{\n    struct f_malloc_block *blk;\n    int ret = -1;\n    blk = malloc_entry[MEMPOOL(pool)];\n    while(blk) {\n        uint8_t *mem_start = (uint8_t *)blk + sizeof(struct f_malloc_block);\n        uint8_t *mem_end   = mem_start + blk->size;\n        if ( (ptr >= mem_start) && (ptr < mem_end) ) {\n            if (block_valid(blk) && in_use(blk))\n                ret =  blk->pid;\n            else\n                ret = -1;\n            break;\n        }\n        blk = blk->next;\n    }\n    return ret;\n}\n\nint fmalloc_owner(const void *_ptr)\n{\n    int ret = fmalloc_check_block_owner(MEM_USER, (uint8_t *)_ptr);\n#ifdef CONFIG_SRAM_EXTRA\n    if (ret == -1)\n        ret = fmalloc_check_block_owner(MEM_EXTRA, (uint8_t *)_ptr);\n#endif\n    return ret;\n}\n\nint fmalloc_chown(const void *ptr, uint16_t pid)\n{\n    struct f_malloc_block *blk = (struct f_malloc_block *) ( ((uint8_t *)ptr)  - sizeof(struct f_malloc_block));\n    if (block_valid(blk))\n        blk->pid = pid;\n}\n\nint mem_trylock(void)\n{\n    return mutex_trylock(mlock);\n}\n\nint mem_lock(void)\n{\n    return suspend_on_mutex_lock(mlock);\n}\n\nvoid mem_unlock(void)\n{\n    mutex_unlock(mlock);\n}\n\n/* Syscalls back-end (for userspace memory call handling) */\nvoid *sys_malloc_hdlr(int size)\n{\n    void *addr;\n    if (mem_lock() < 0)\n        return (void *)SYS_CALL_AGAIN;\n    addr = u_malloc(size);\n    mem_unlock();\n    return addr;\n}\n\nint sys_free_hdlr(void *addr)\n{\n    struct f_malloc_block * blk;\n    if ((task_ptr_valid(addr) != 0) || (addr == NULL))\n        return -1;\n\n    blk = (struct f_malloc_block *)((uint8_t *)addr - sizeof(struct f_malloc_block));\n\n    if (mem_lock() < 0)\n        return SYS_CALL_AGAIN;\n    f_free(addr);\n    blk_rearrange(blk);\n    mem_unlock();\n    return 0;\n}\n\nvoid *sys_calloc_hdlr(int n, int size)\n{\n    void *addr;\n    if (mem_lock() < 0)\n        return (void *)SYS_CALL_AGAIN;\n    addr = u_calloc(n, size);\n    mem_unlock();\n    return addr;\n}\n\nvoid *sys_realloc_hdlr(void *addr, int size)\n{\n    void *naddr;\n    if (mem_lock() < 0)\n        return (void *)SYS_CALL_AGAIN;\n    naddr = u_realloc(addr, size);\n    mem_unlock();\n    return naddr;\n}\n\n/*------------------*/\n/* Test functions   */\n/*------------------*/\n\n\n#if defined __linux__ || defined _WIN32 /* test application */\n    int task_segfault(uint32_t mem, uint32_t inst, int flags) {\n        dbg_malloc(\"Memory violation\\n\");\n        exit(1);\n    }\n\n    void print_malloc_stats(void)\n    {\n        dbg_malloc(\"\\n=== FROSTED MALLOC STATS ===\\n\");\n        dbg_malloc(\"--> malloc calls: %d\\n\", f_malloc_stats[0].malloc_calls);\n        dbg_malloc(\"--> free   calls: %d\\n\", f_malloc_stats[0].free_calls);\n        dbg_malloc(\"--> objects allocated: %d\\n\", f_malloc_stats[0].objects_allocated);\n        dbg_malloc(\"--> memory  allocated: %d\\n\", f_malloc_stats[0].mem_allocated);\n        dbg_malloc(\"=== FROSTED MALLOC STATS ===\\n\\n\");\n    }\n\n    void print_malloc_entries(void)\n    {\n        struct f_malloc_block *blk = malloc_entry[0];\n        uint32_t i = 0;\n\n        /* See if we can find a free block that fits */\n        while (blk) /* last entry will break the loop */\n        {\n            dbg_malloc(\">>> Entry #%d: \\n\", i);\n            dbg_malloc(\"    Address (blk) %p \\n\", blk);\n            dbg_malloc(\"    Address (usr) %p \\n\", ((uint8_t*)blk) + sizeof(struct f_malloc_block));\n            dbg_malloc(\"    Prev: %p \\n\", blk->prev);\n            dbg_malloc(\"    Next: %p \\n\", blk->next);\n            dbg_malloc(\"    Size (usr) %d \\n\", blk->size);\n            dbg_malloc(\"    Flags: %08x \\n\", blk->flags);\n            dbg_malloc(\"    Magic: 0x%08x \\n\", blk->magic);\n            i++;\n            blk = blk->next;\n        }\n    }\n\n    int main(int argc, char ** argv)\n    {\n        void * test10 = f_malloc(0, 10);\n        void * test200 = f_malloc(0, 200);\n        void * test100 = NULL;\n        dbg_malloc(\"test10: %p\\n\", test10);\n        dbg_malloc(\"test200: %p\\n\", test200);\n        f_free(test10);\n        print_malloc_stats();\n        print_malloc_entries();\n\n        dbg_malloc(\"\\nTrying to re-use freed memory + allocate more\\n\");\n        test10 = f_malloc(0, 10); // this should re-use exisiting entry\n        test100 = f_malloc(0, 100); // this should alloc more memory through sbrk\n        print_malloc_stats();\n        print_malloc_entries();\n\n        dbg_malloc(\"\\nFreeing all of the memory\\n\");\n        f_free(test10);\n        f_free(test200);\n        f_free(test100);\n        print_malloc_stats();\n        print_malloc_entries();\n\n        dbg_malloc(\"Trying to re-use freed memory\\n\");\n        test100 = f_malloc(0, 100); // this should re-use memory in the freed pool\n        print_malloc_stats();\n        print_malloc_entries();\n        f_free(test100);\n\n        dbg_malloc(\"Allocating more memory\\n\");\n        test10 = f_malloc(0, 10);\n        test200 = f_malloc(0, 200);\n        print_malloc_stats();\n        print_malloc_entries();\n        f_free(test10);\n        f_free(test200);\n\n        dbg_malloc(\"Test Realloc \\n\");\n        test10 = f_malloc(0,10);\n        test100 = f_malloc(0,110);\n        test200 = f_malloc(0,1);\n        if (!test10 || !test100 || !test200) {\n            dbg_malloc(\"malloc failed!\\n\");\n            exit(1);\n        }\n        print_malloc_stats();\n        print_malloc_entries();\n        test10 = f_realloc(0, test10, 210);\n        test100 = f_realloc(0, test100, 2010);\n        test200 = f_realloc(0, test200, 2);\n        if (!test10 || !test100 || !test200) {\n            dbg_malloc(\"realloc failed!\\n\");\n            exit(1);\n        }\n        print_malloc_stats();\n        print_malloc_entries();\n\n        dbg_malloc(\"\\nFreeing all of the memory\\n\");\n        f_free(test10);\n        f_free(test200);\n        f_free(test100);\n        print_malloc_stats();\n        print_malloc_entries();\n\n        return 0;\n    }\n#endif\n\n\n\n"
  },
  {
    "path": "kernel/malloc.h",
    "content": "#ifndef _FROSTED_MALLOC_H\n#define _FROSTED_MALLOC_H\n\n#include \"string.h\"\n#include \"stdint.h\"\n\n#define MEM_KERNEL 0\n#define MEM_USER   1\n#define MEM_TASK   2\n#define MEM_EXTRA 9\n\n#ifdef CONFIG_TCPIP_MEMPOOL\n#   define MEM_TCPIP  4\n#   define MEM_OWNER_MASK 7\n#else\n#   define MEM_TCPIP MEM_KERNEL\n#   define MEM_OWNER_MASK 3\n#endif\n\n\n\nstruct f_malloc_stats {\n    uint32_t malloc_calls;\n    uint32_t free_calls;\n    uint32_t objects_allocated;\n    uint32_t mem_allocated;\n};\n\nvoid * u_malloc(size_t size);\nvoid * f_malloc(int flags, size_t size);\nvoid * f_calloc(int flags, size_t num, size_t size);\nvoid* f_realloc(int flags, void* ptr, size_t size);\nvoid f_free(void * ptr);\n\n/* Free up heap of a specific pid */\nvoid f_proc_heap_free(int pid);\n\n/* Get heap usage for specific pid */\nuint32_t f_proc_heap_count(int pid);\n\n#endif /* _FROSTED_MALLOC_H */\n"
  },
  {
    "path": "kernel/module.c",
    "content": "/*  \n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as \n *      published by the Free Software Foundation.\n *      \n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */  \n#include \"frosted.h\"\n\nstruct address_family {\n    struct module *mod;\n    uint16_t family; \n    struct address_family *next;\n};\n\nstruct module *MODS = NULL;\nstruct address_family *AF = NULL;\n\nint register_module(struct module *m)\n{\n    m->next = MODS;\n    MODS = m;\n    return 0;\n}\n\nint unregister_module(struct module *m)\n{\n    struct module *cur = MODS;\n    while (cur) {\n        /*XXX*/\n        cur = cur->next;\n    }\n}\n\nstruct module *module_search(char *name)\n{\n    struct module *m = MODS;\n    while(m) {\n        if (strcmp(m->name, name) == 0)\n            return m;\n        m = m->next;\n    }\n    return NULL;\n}\n\nstatic struct module *af_to_module(uint16_t family)\n{\n    struct address_family *af = AF;\n    while (af) {\n        if (af->family == family)\n            return af->mod;\n        af = af->next;\n    }\n    return NULL;\n}\n\nint register_addr_family(struct module *m, uint16_t family)\n{\n   struct address_family *af;\n   if (af_to_module(family))\n       return -1; /* Another module already claimed this AF */\n   af = kalloc(sizeof(struct address_family));\n   if (!af)\n       return -1;\n   af->family = family;\n   af->mod = m;\n   af->next = AF;\n   AF = af;\n   return 0;\n} \n\nint sys_read_hdlr(int fd, void *buf, int len)\n{\n    struct fnode *fno = task_filedesc_get(fd);\n    if (!task_fd_readable(fd))\n        return -EPERM;\n    if (task_ptr_valid(buf))\n        return -EACCES;\n    if (fno && fno->owner->ops.read) {\n        return fno->owner->ops.read(fno, buf, len);\n    } else if (fno->owner && fno->owner->ops.recvfrom) {\n        return fno->owner->ops.recvfrom(fd, buf, len, 0, NULL, NULL);\n    }\n    return -ENOENT;\n}\n\nint sys_write_hdlr(int fd, void *buf, int len)\n{\n    struct fnode *fno = task_filedesc_get(fd);\n    if (!task_fd_writable(fd))\n        return -EPERM;\n    if (task_ptr_valid(buf))\n        return -EACCES;\n    if (!fno)\n        return -ENOENT;\n    if (fno->owner && fno->owner->ops.write) {\n        return fno->owner->ops.write(fno, buf, len);\n    } else if (fno->owner && fno->owner->ops.sendto) {\n        return fno->owner->ops.sendto(fd, buf, len, 0, NULL, 0);\n    }\n    return -EOPNOTSUPP;\n}\n\nint sys_socket_hdlr(int family, int type, int proto)\n{\n    struct module *m = af_to_module(family);\n    if(!m || !(m->ops.socket))\n        return -EOPNOTSUPP;\n    return m->ops.socket(family, type, proto);\n}\n\nint sys_bind_hdlr(int sd, struct sockaddr_env *se)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(se))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.bind) {\n        return fno->owner->ops.bind(sd, se->se_addr, se->se_len);\n    }\n    return -EINVAL;\n}\n\nint sys_listen_hdlr(int sd, unsigned int backlog)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (fno && fno->owner && fno->owner->ops.listen) {\n        return fno->owner->ops.listen(sd, backlog);\n    }\n    return -EINVAL;\n}\n\nint sys_connect_hdlr(int sd, struct sockaddr_env *se)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(se))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.connect) {\n        return fno->owner->ops.connect(sd, se->se_addr, se->se_len);\n    }\n    return -EINVAL;\n}\n\nint sys_accept_hdlr(int sd, struct sockaddr_env *se)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(se))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.accept) {\n        if (se)\n            return fno->owner->ops.accept(sd, se->se_addr, &(se->se_len));\n        else\n            return fno->owner->ops.accept(sd, NULL, NULL);\n    }\n    return -EINVAL;\n}\n\n\nint sys_recvfrom_hdlr(int sd, void *buf, int len, int flags, struct sockaddr_env *se)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(buf))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.recvfrom) {\n        if (se) {\n            if (task_ptr_valid(se))\n                return -EACCES;\n            return fno->owner->ops.recvfrom(sd, buf, len, flags, se->se_addr, &(se->se_len));\n        } else\n            return fno->owner->ops.recvfrom(sd, buf, len, flags, NULL, NULL);\n    }\n    return -EINVAL;\n}\n\nint sys_sendto_hdlr(int sd, const void *buf, int len, int flags, struct sockaddr_env *se )\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (fno && fno->owner && fno->owner->ops.sendto) {\n        if (se) {\n            if (task_ptr_valid(buf))\n                return -EACCES;\n            return fno->owner->ops.sendto(sd, buf, len, flags, se->se_addr, se->se_len);\n        } else\n            return fno->owner->ops.sendto(sd, buf, len, flags, NULL, 0);\n    }\n    return -EINVAL;\n}\n\nint sys_shutdown_hdlr(int sd, int how)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (fno && fno->owner && fno->owner->ops.shutdown) {\n        return fno->owner->ops.shutdown(sd, how);\n    }\n    return -EINVAL;\n}\n\nint sys_setsockopt_hdlr(int sd, int level, int optname, void *optval, unsigned int optlen)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(optval))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.setsockopt) {\n        return fno->owner->ops.setsockopt(sd, level, optname, optval, optlen);\n    }\n    return -EINVAL;\n}\n\nint sys_getsockopt_hdlr(int sd, int level, int optname, void *optval, unsigned int *optlen)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(optval))\n        return -EACCES;\n    if (task_ptr_valid(optlen))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.getsockopt) {\n        return fno->owner->ops.getsockopt(sd, level, optname, optval, optlen);\n    }\n    return -EINVAL;\n}\n\nint sys_getsockname_hdlr(int sd, struct sockaddr_env *se)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(se))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.getsockname) {\n        return fno->owner->ops.getsockname(sd, se->se_addr, &(se->se_len));\n    }\n    return -EINVAL;\n}\n\nint sys_getpeername_hdlr(int sd, struct sockaddr_env *se)\n{\n    struct fnode *fno = task_filedesc_get(sd);\n    if (task_ptr_valid(se))\n        return -EACCES;\n    if (fno && fno->owner && fno->owner->ops.getpeername) {\n        return fno->owner->ops.getpeername(sd, se->se_addr, &(se->se_len));\n    }\n    return -EINVAL;\n}\n"
  },
  {
    "path": "kernel/mpu.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors:\n *\n */\n\n#include \"frosted.h\"\n#include \"cm3/mpu.h\"\n#include \"libopencmsis/core_cm3.h\"\n\n\n#ifdef CONFIG_MPU\n\n#define MPUSIZE_1K      (0x09 << 1)\n#define MPUSIZE_2K      (0x0a << 1)\n#define MPUSIZE_4K      (0x0b << 1)\n#define MPUSIZE_8K      (0x0c << 1)\n#define MPUSIZE_16K     (0x0d << 1)\n#define MPUSIZE_32K     (0x0e << 1)\n#define MPUSIZE_64K     (0x0f << 1)\n#define MPUSIZE_128K    (0x10 << 1)\n#define MPUSIZE_256K    (0x11 << 1)\n#define MPUSIZE_512K    (0x12 << 1)\n#define MPUSIZE_1M      (0x13 << 1)\n#define MPUSIZE_2M      (0x14 << 1)\n#define MPUSIZE_4M      (0x15 << 1)\n#define MPUSIZE_8M      (0x16 << 1)\n#define MPUSIZE_16M     (0x17 << 1)\n#define MPUSIZE_32M     (0x18 << 1)\n#define MPUSIZE_64M     (0x19 << 1)\n#define MPUSIZE_128M    (0x1a << 1)\n#define MPUSIZE_256M    (0x1b << 1)\n#define MPUSIZE_512M    (0x1c << 1)\n#define MPUSIZE_1G      (0x1d << 1)\n#define MPUSIZE_2G      (0x1e << 1)\n#define MPUSIZE_4G      (0x1f << 1)\n#define MPUSIZE_ERR     (0xFFFFFFFFu)\n\n\n#define FLASH_START       (0x00000000)\n#define RAM_START         (0x20000000)\n#define DEV_START         (0x40000000)\n#define EXTRAM_START      (0xC0000000)\n#define EXTFLASH_START    (0x80000000)\n#define EXTDEV_START      (0xA0000000)\n#define REG_START         (0xE0000000)\n\nuint32_t mpu_size(uint32_t size)\n{\n    switch(size) {\n        case (1 * 1024):\n            return MPUSIZE_1K;\n        case (2 * 1024):\n            return MPUSIZE_2K;\n        case (4 * 1024):\n            return MPUSIZE_4K;\n        case (8 * 1024):\n            return MPUSIZE_8K;\n        case (16 * 1024):\n            return MPUSIZE_16K;\n        case (32 * 1024):\n            return MPUSIZE_32K;\n        case (64 * 1024):\n            return MPUSIZE_64K;\n        case (128 * 1024):\n            return MPUSIZE_128K;\n        case (256 * 1024):\n            return MPUSIZE_256K;\n        case (512 * 1024):\n            return MPUSIZE_512K;\n        case (1 * 1024 * 1024):\n            return MPUSIZE_1M;\n        case (2 * 1024 * 1024):\n            return MPUSIZE_2M;\n        case (4 * 1024 * 1024):\n            return MPUSIZE_4M;\n        case (8 * 1024 * 1024):\n            return MPUSIZE_8M;\n        default:\n            return MPUSIZE_ERR;\n    }\n}\n\n\nstatic uint32_t mpu_bits = 0;\n\nint mpu_present(void)\n{\n    mpu_bits = MPU_TYPE;\n    if (mpu_bits != 0)\n        return 1;\n    return 0;\n}\n\nint mpu_enable(void)\n{\n    if (!mpu_bits)\n        return -1;\n    MPU_CTRL = MPU_CTRL_ENABLE; //| MPU_CTRL_PRIVDEFENA;\n    return 0;\n}\n\nint mpu_disable(void)\n{\n    if (!mpu_bits)\n        return -1;\n    MPU_CTRL = 0;\n    return 0;\n}\n\nstatic void mpu_select(uint32_t region)\n{\n    MPU_RNR = region;\n}\n\nstatic void mpu_setattr(int region, uint32_t attr)\n{\n    mpu_select(region);\n    MPU_RASR = attr;\n}\n\nstatic void mpu_setaddr(int region, uint32_t addr)\n{\n    mpu_select(region);\n    MPU_RBAR = addr;\n}\n\n\nvoid mpu_init(void)\n{\n    if (!mpu_present())\n        return;\n\n    /* User area: prio 0, from start */\n    mpu_setaddr(0, 0);              /* Userspace memory block   0x00000000 (1G) - Internal flash is an exception of this */\n    mpu_setattr(0, MPUSIZE_1G | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRW_URW);\n\n    mpu_setaddr(1, EXTRAM_START);   /* External RAM bank        0x60000000 (512M) */\n    mpu_setattr(1, MPUSIZE_512M   | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRW_URW);\n\n    /* Read-only sectors */\n    mpu_setaddr(2, FLASH_START);    /* Internal Flash           0x00000000 - 0x0FFFFFFF (256M) */\n    mpu_setattr(2, MPUSIZE_256M | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRO_URO);\n\n    /* System (No user access) */\n    mpu_setaddr(3, RAM_START);      /* Kernel memory            0x20000000 (CONFIG_KRAM_SIZE KB) */\n    mpu_setattr(3, mpu_size(CONFIG_KRAM_SIZE << 10) | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRW_UNO);\n\n    /* Priority 4 reserved for task stack exception in kernel memory */\n\n    mpu_setaddr(5, DEV_START);      /* Peripherals              0x40000000 (512MB)*/\n    mpu_setattr(5, MPUSIZE_1G | MPU_RASR_ENABLE | MPU_RASR_ATTR_S | MPU_RASR_ATTR_B | MPU_RASR_ATTR_AP_PRW_UNO);\n    mpu_setaddr(6, EXTDEV_START);   /* External Peripherals     0xA0000000 (1GB)   */\n    mpu_setattr(6, MPUSIZE_1G | MPU_RASR_ENABLE | MPU_RASR_ATTR_S | MPU_RASR_ATTR_B | MPU_RASR_ATTR_AP_PRW_UNO);\n    mpu_setaddr(7, REG_START);      /* System Level             0xE0000000 (256MB) */\n    mpu_setattr(7, MPUSIZE_256M | MPU_RASR_ENABLE | MPU_RASR_ATTR_S | MPU_RASR_ATTR_B | MPU_RASR_ATTR_AP_PRW_UNO);\n\n\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    SCB_SHCSR |= SCB_SHCSR_MEMFAULTENA;\n#endif\n    mpu_enable();\n}\n\nvoid mpu_task_on(void *stack)\n{\n    mpu_disable();\n    mpu_setaddr(4, (int)(stack + 20));\n    mpu_setattr(4, mpu_size(CONFIG_TASK_STACK_SIZE) | MPU_RASR_ENABLE | MPU_RASR_ATTR_SCB | MPU_RASR_ATTR_AP_PRW_URW);\n    mpu_enable();\n}\n#endif\n"
  },
  {
    "path": "kernel/mpu.h",
    "content": "#ifndef FROSTED_MPU_H\n#define FROSTED_MPU_H\n\n#ifdef CONFIG_MPU\nvoid mpu_init(void);\nvoid mpu_task_on(void *stack);\n#else\n#   define mpu_init() do{}while(0)\n#   define mpu_task_on(x) do{}while(0)\n#endif\n\n\n\n\n#endif\n\n"
  },
  {
    "path": "kernel/mutex.S",
    "content": "\n.syntax unified\n\n/* Lock function.\n * On success, return 0. \n * On failure, return -1 (Locked, try again later).\n */\n\n.global _mutex_lock\n_mutex_lock:\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   LDREX   r1, [r0]\n#elif defined(__ARCH_V6M__)\n   CPSID   i\n   LDR     r1, [r0]\n#endif\n   CMP     r1, #0             // Test if mutex holds the value 0\n   BEQ     _mutex_lock_fail   // If it does, return 0\n   SUBS    r1, #1             // If not, decrement temporary copy\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   STREX   r2, r1, [r0]       // Attempt Store-Exclusive\n   CMP     r2, #0             // Check if Store-Exclusive succeeded\n   BNE     _mutex_lock        // If Store-Exclusive failed, retry from start\n   DMB                        // Required before accessing protected resource\n#elif defined(__ARM_ARCH_6M__)\n   STR     r1, [r0]\n   CPSIE   i\n#endif\n   MOVS    r0, #0             // Successfully locked.\n   BX      lr\n_mutex_lock_fail:\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   DMB\n   MOV     r0, #-1              // Already locked!\n#elif defined(__ARM_ARCH_6M__)\n   CPSIE   i\n   MOVS    r2, #0               // Already locked!\n   MVNS    r0, r2\n#endif\n   BX      lr\n\n/* Unlock mutex. \n * On success, return 0. \n * On failure, return -1 (Already unlocked!).\n */\n\n.global _mutex_unlock\n_mutex_unlock:\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   LDREX   r1, [r0]\n#elif defined(__ARM_ARCH_6M__)\n   CPSID    i\n   LDR      r1, [r0]\n#endif\n   CMP     r1, #0               // Test if mutex holds the value 0\n   BNE     _mutex_unlock_fail   // If it does not, it's already locked!\n   ADDS    r1, #1               // Increment temporary copy\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   STREX   r2, r1, [r0]         // Attempt Store-Exclusive\n   CMP     r2, #0               // Check if Store-Exclusive succeeded\n   BNE     _mutex_unlock        // Store failed - retry immediately\n   DMB                          // Required before releasing protected resource\n#elif defined(__ARM_ARCH_6M__)\n   STR     r1, [r0]\n   CPSIE   i\n#endif\n   MOVS    r0, #0               // Successfully unlocked.\n   BX      lr\n_mutex_unlock_fail:\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   DMB\n   MOV     r0, #-1              // Already locked!\n#elif defined(__ARM_ARCH_6M__)\n   CPSIE   i\n   MOVS    r2, #0               // Already locked!\n   MVNS    r0, r2\n#endif\n   BX      lr\n\n"
  },
  {
    "path": "kernel/net/Kconfig",
    "content": "if PICOTCP \n\nmenu \"picoTCP configuration\"\n\nconfig CONFIG_PICOTCP_IPV4\n    bool \"Support for IP version 4\"\n    default y\n\nconfig CONFIG_PICOTCP_IPV6\n    bool \"Support for IP version 6\"\n    default n\n\nconfig CONFIG_PICOTCP_TCP\n    bool \"Support for TCP\"\n    default y\n\nconfig CONFIG_PICOTCP_UDP\n    bool \"Support for UDP\"\n    default y\n\nconfig CONFIG_PICOTCP_DNS\n    bool \"Support for DNS client\"\n    default y\n\nconfig CONFIG_PICOTCP_MCAST\n    bool \"Support for Multicast\"\n    default n\n\nconfig CONFIG_PICOTCP_NAT\n    bool \"Support for NAT\"\n    default n\n\nconfig CONFIG_PICOTCP_IPFILTER\n    bool \"Support for IP Filter\"\n    default n\n\nconfig CONFIG_PICOTCP_LOOP\n    bool \"Support for loopback device\"\n    default y\n\nconfig CONFIG_PICOTCP_DEBUG\n    bool \"Activate debugging symbols\"\n    default n\n\nendmenu\nendif\n"
  },
  {
    "path": "kernel/net/if.h",
    "content": "/*\n * Copyright (c) 1982, 1986, 1989, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *\tThis product includes software developed by the University of\n *\tCalifornia, Berkeley and its contributors.\n * 4. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)if.h\t8.1 (Berkeley) 6/10/93\n * $FreeBSD: src/sys/net/if.h,v 1.71 2002/03/19 21:54:16 alfred Exp $\n */\n\n#ifndef _NET_IF_H_\n#define\t_NET_IF_H_\n#include \"frosted_api.h\"\n\n\nstruct ifnet;\n\n/*\n * Length of interface external name, including terminating '\\0'.\n * Note: this is the same size as a generic device's external name.\n */\n#define\t\tIFNAMSIZ\t16\n#define\t\tIF_NAMESIZE\tIFNAMSIZ\n#define\t\tIF_MAXUNIT\t0x7fff\t/* ifp->if_unit is only 15 bits */\n\n/*\n * Structure describing information about an interface\n * which may be of interest to management entities.\n */\nstruct if_data {\n\t/* generic interface information */\n\tu_char\tifi_type;\t\t/* ethernet, tokenring, etc */\n\tu_char\tifi_physical;\t\t/* e.g., AUI, Thinnet, 10base-T, etc */\n\tu_char\tifi_addrlen;\t\t/* media address length */\n\tu_char\tifi_hdrlen;\t\t/* media header length */\n\tu_char\tifi_recvquota;\t\t/* polling quota for receive intrs */\n\tu_char\tifi_xmitquota;\t\t/* polling quota for xmit intrs */\n\tu_long\tifi_mtu;\t\t/* maximum transmission unit */\n\tu_long\tifi_metric;\t\t/* routing metric (external only) */\n\tu_long\tifi_baudrate;\t\t/* linespeed */\n\t/* volatile statistics */\n\tu_long\tifi_ipackets;\t\t/* packets received on interface */\n\tu_long\tifi_ierrors;\t\t/* input errors on interface */\n\tu_long\tifi_opackets;\t\t/* packets sent on interface */\n\tu_long\tifi_oerrors;\t\t/* output errors on interface */\n\tu_long\tifi_collisions;\t\t/* collisions on csma interfaces */\n\tu_long\tifi_ibytes;\t\t/* total number of octets received */\n\tu_long\tifi_obytes;\t\t/* total number of octets sent */\n\tu_long\tifi_imcasts;\t\t/* packets received via multicast */\n\tu_long\tifi_omcasts;\t\t/* packets sent via multicast */\n\tu_long\tifi_iqdrops;\t\t/* dropped on input, this interface */\n\tu_long\tifi_noproto;\t\t/* destined for unsupported protocol */\n\tu_long\tifi_hwassist;\t\t/* HW offload capabilities */\n\tu_long\tifi_unused;\t\t/* XXX was ifi_xmittiming */\n\tstruct\ttimeval ifi_lastchange;\t/* time of last administrative change */\n};\n\n#define\tIFF_UP\t\t0x1\t\t/* interface is up */\n#define\tIFF_BROADCAST\t0x2\t\t/* broadcast address valid */\n#define\tIFF_DEBUG\t0x4\t\t/* turn on debugging */\n#define\tIFF_LOOPBACK\t0x8\t\t/* is a loopback net */\n#define\tIFF_POINTOPOINT\t0x10\t\t/* interface is point-to-point link */\n#define\tIFF_NOTRAILERS\t0x20\t\t/* avoid use of trailers */\n#define\tIFF_RUNNING\t0x40\t\t/* resources allocated */\n#define\tIFF_NOARP\t0x80\t\t/* no address resolution protocol */\n#define\tIFF_PROMISC\t0x100\t\t/* receive all packets */\n#define\tIFF_ALLMULTI\t0x200\t\t/* receive all multicast packets */\n#define\tIFF_OACTIVE\t0x400\t\t/* transmission in progress */\n#define\tIFF_SIMPLEX\t0x800\t\t/* can't hear own transmissions */\n#define\tIFF_LINK0\t0x1000\t\t/* per link layer defined bit */\n#define\tIFF_LINK1\t0x2000\t\t/* per link layer defined bit */\n#define\tIFF_LINK2\t0x4000\t\t/* per link layer defined bit */\n#define\tIFF_ALTPHYS\tIFF_LINK2\t/* use alternate physical connection */\n#define\tIFF_MULTICAST\t0x8000\t\t/* supports multicast */\n\n/*\n * The following flag(s) ought to go in if_flags, but we cannot change\n * struct ifnet because of binary compatibility, so we store them in\n * if_ipending, which is not used so far.\n * If possible, make sure the value is not conflicting with other\n * IFF flags, so we have an easier time when we want to merge them.\n */\n#define\tIFF_POLLING\t0x10000\t\t/* Interface is in polling mode. */\n\n/* flags set internally only: */\n#define\tIFF_CANTCHANGE \\\n\t(IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\\\n\t    IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_NOTRAILERS)\n\n/* Capabilities that interfaces can advertise. */\n#define IFCAP_RXCSUM\t\t0x0001  /* can offload checksum on RX */\n#define IFCAP_TXCSUM\t\t0x0002  /* can offload checksum on TX */\n#define IFCAP_NETCONS\t\t0x0004  /* can be a network console */\n\n#define IFCAP_HWCSUM\t\t(IFCAP_RXCSUM | IFCAP_TXCSUM)\n\n#define\tIFQ_MAXLEN\t50\n#define\tIFNET_SLOWHZ\t1\t\t/* granularity is 1 second */\n\n/*\n * Message format for use in obtaining information about interfaces\n * from getkerninfo and the routing socket\n */\nstruct if_msghdr {\n\tu_short\tifm_msglen;\t/* to skip over non-understood messages */\n\tu_char\tifm_version;\t/* future binary compatibility */\n\tu_char\tifm_type;\t/* message type */\n\tint\tifm_addrs;\t/* like rtm_addrs */\n\tint\tifm_flags;\t/* value of if_flags */\n\tu_short\tifm_index;\t/* index for associated ifp */\n\tstruct\tif_data ifm_data;/* statistics and other data about if */\n};\n\n/*\n * Message format for use in obtaining information about interface addresses\n * from getkerninfo and the routing socket\n */\nstruct ifa_msghdr {\n\tu_short\tifam_msglen;\t/* to skip over non-understood messages */\n\tu_char\tifam_version;\t/* future binary compatibility */\n\tu_char\tifam_type;\t/* message type */\n\tint\tifam_addrs;\t/* like rtm_addrs */\n\tint\tifam_flags;\t/* value of ifa_flags */\n\tu_short\tifam_index;\t/* index for associated ifp */\n\tint\tifam_metric;\t/* value of ifa_metric */\n};\n\n/*\n * Message format for use in obtaining information about multicast addresses\n * from the routing socket\n */\nstruct ifma_msghdr {\n\tu_short\tifmam_msglen;\t/* to skip over non-understood messages */\n\tu_char\tifmam_version;\t/* future binary compatibility */\n\tu_char\tifmam_type;\t/* message type */\n\tint\tifmam_addrs;\t/* like rtm_addrs */\n\tint\tifmam_flags;\t/* value of ifa_flags */\n\tu_short\tifmam_index;\t/* index for associated ifp */\n};\n\n/*\n * Message format announcing the arrival or departure of a network interface.\n */\nstruct if_announcemsghdr {\n\tu_short\tifan_msglen;\t/* to skip over non-understood messages */\n\tu_char\tifan_version;\t/* future binary compatibility */\n\tu_char\tifan_type;\t/* message type */\n\tu_short\tifan_index;\t/* index for associated ifp */\n\tchar\tifan_name[IFNAMSIZ]; /* if name, e.g. \"en0\" */\n\tu_short\tifan_what;\t/* what type of announcement */\n};\n\n#define\tIFAN_ARRIVAL\t0\t/* interface arrival */\n#define\tIFAN_DEPARTURE\t1\t/* interface departure */\n\n/*\n * Interface request structure used for socket\n * ioctl's.  All interface ioctl's must have parameter\n * definitions which begin with ifr_name.  The\n * remainder may be interface specific.\n */\nstruct\tifreq {\n\tchar\tifr_name[IFNAMSIZ];\t\t/* if name, e.g. \"en0\" */\n\tunion {\n\t\tstruct\tsockaddr ifru_addr;\n\t\tstruct\tsockaddr ifru_dstaddr;\n\t\tstruct\tsockaddr ifru_broadaddr;\n\t\tstruct\tsockaddr ifru_netmask;\n\t\tstruct\tsockaddr ifru_hwaddr;\n\t\tshort\tifru_flags[2];\n\t\tshort\tifru_index;\n\t\tint\tifru_metric;\n\t\tint\tifru_mtu;\n\t\tint\tifru_phys;\n\t\tint\tifru_media;\n\t\tcaddr_t\tifru_data;\n\t\tint\tifru_cap[2];\n\t} ifr_ifru;\n#define\tifr_addr\tifr_ifru.ifru_addr\t/* address */\n#define\tifr_dstaddr\tifr_ifru.ifru_dstaddr\t/* other end of p-to-p link */\n#define\tifr_broadaddr\tifr_ifru.ifru_broadaddr\t/* broadcast address */\n#define\tifr_netmask\tifr_ifru.ifru_netmask\t/* interface net mask\t*/\n#define\tifr_flags\tifr_ifru.ifru_flags[0]\t/* flags */\n#define\tifr_prevflags\tifr_ifru.ifru_flags[1]\t/* flags */\n#define\tifr_metric\tifr_ifru.ifru_metric\t/* metric */\n#define\tifr_mtu\t\tifr_ifru.ifru_mtu\t/* mtu */\n#define ifr_phys\tifr_ifru.ifru_phys\t/* physical wire */\n#define ifr_media\tifr_ifru.ifru_media\t/* physical media */\n#define\tifr_data\tifr_ifru.ifru_data\t/* for use by interface */\n#define\tifr_reqcap\tifr_ifru.ifru_cap[0]\t/* requested capabilities */\n#define\tifr_curcap\tifr_ifru.ifru_cap[1]\t/* current capabilities */\n#define\tifr_index\tifr_ifru.ifru_index\t/* interface index */\n};\n\nstruct ifaliasreq {\n\tchar\tifra_name[IFNAMSIZ];\t\t/* if name, e.g. \"en0\" */\n\tstruct\tsockaddr ifra_addr;\n\tstruct\tsockaddr ifra_broadaddr;\n\tstruct\tsockaddr ifra_mask;\n};\n\nstruct ifmediareq {\n\tchar\tifm_name[IFNAMSIZ];\t/* if name, e.g. \"en0\" */\n\tint\tifm_current;\t\t/* current media options */\n\tint\tifm_mask;\t\t/* don't care mask */\n\tint\tifm_status;\t\t/* media status */\n\tint\tifm_active;\t\t/* active options */\n\tint\tifm_count;\t\t/* # entries in ifm_ulist array */\n\tint\t*ifm_ulist;\t\t/* media words */\n};\n\n/* \n * Structure used to retrieve aux status data from interfaces.\n * Kernel suppliers to this interface should respect the formatting\n * needed by ifconfig(8): each line starts with a TAB and ends with\n * a newline.  The canonical example to copy and paste is in if_tun.c.\n */\n\n#define\tIFSTATMAX\t800\t\t/* 10 lines of text */\nstruct ifstat {\n\tchar\tifs_name[IFNAMSIZ];\t/* if name, e.g. \"en0\" */\n\tchar\tascii[IFSTATMAX + 1];\n};\n\n/*\n * Structure used in SIOCGIFCONF request.\n * Used to retrieve interface configuration\n * for machine (useful for programs which\n * must know all networks accessible).\n */\nstruct\tifconf {\n\tint\tifc_len;\t\t/* size of associated buffer */\n\tunion {\n\t\tcaddr_t\tifcu_buf;\n\t\tstruct\tifreq *ifcu_req;\n\t} ifc_ifcu;\n#define\tifc_buf\tifc_ifcu.ifcu_buf\t/* buffer address */\n#define\tifc_req\tifc_ifcu.ifcu_req\t/* array of structures returned */\n};\n\n\n/*\n * Structure for SIOC[AGD]LIFADDR\n */\nstruct if_laddrreq {\n\tchar\tiflr_name[IFNAMSIZ];\n\tu_int\tflags;\n#define\tIFLR_PREFIX\t0x8000  /* in: prefix given  out: kernel fills id */\n\tu_int\tprefixlen;         /* in/out */\n\tstruct\tsockaddr_storage addr;   /* in/out */\n\tstruct\tsockaddr_storage dstaddr; /* out */\n};\n\n#ifdef _KERNEL\n#ifdef MALLOC_DECLARE\nMALLOC_DECLARE(M_IFADDR);\nMALLOC_DECLARE(M_IFMADDR);\n#endif\n#endif\n\n#ifndef _KERNEL\nstruct if_nameindex {\n\tu_int\tif_index;\t/* 1, 2, ... */\n\tchar\t*if_name;\t/* null terminated name: \"le0\", ... */\n};\n\n__BEGIN_DECLS\nu_int\t if_nametoindex(const char *);\nchar\t*if_indextoname(u_int, char *);\nstruct\t if_nameindex *if_nameindex(void);\nvoid\t if_freenameindex(struct if_nameindex *);\n__END_DECLS\n#endif\n\n#ifdef _KERNEL\nstruct thread;\n\n/* XXX - this should go away soon. */\n#include <net/if_var.h>\n#endif\n\n#endif /* !_NET_IF_H_ */\n"
  },
  {
    "path": "kernel/net/pico_lock.c",
    "content": "#include \"frosted.h\"\n#include \"locks.h\"\n\nstatic mutex_t *picotcp_lock = NULL;\nvoid pico_lock_init(void)\n{\n    if (!picotcp_lock)\n        picotcp_lock = mutex_init();\n}\n\nvoid pico_lock(void)\n{\n    if (picotcp_lock)\n        mutex_lock(picotcp_lock);\n}\n\nint pico_trylock(void)\n{\n    if(picotcp_lock)\n        return suspend_on_mutex_lock(picotcp_lock);\n    else\n        return 0;\n}\n\nint pico_trylock_kernel(void)\n{\n    if (!picotcp_lock)\n        return -EAGAIN;\n    return mutex_trylock(picotcp_lock);\n}\n\nvoid pico_unlock(void)\n{\n    if (picotcp_lock) {\n        mutex_unlock(picotcp_lock);\n    }\n}\n"
  },
  {
    "path": "kernel/net/route.h",
    "content": "#ifndef NET_ROUTE_H\n#define NET_ROUTE_H\n#include <frosted.h>\n#include <stdint.h>\n\n\nstruct rtentry {\n\tunsigned long int rt_pad1;\n\tstruct sockaddr rt_dst;\n\tstruct sockaddr rt_gateway;\n\tstruct sockaddr rt_genmask;\n\tunsigned short int rt_flags;\n\tshort int rt_pad2;\n\tunsigned long int rt_pad3;\n\tunsigned char rt_tos;\n\tunsigned char rt_class;\n\tshort int rt_pad4[sizeof(long)/2-1];\n\tshort int rt_metric;\n\tchar *rt_dev;\n\tunsigned long int rt_mtu;\n\tunsigned long int rt_window;\n\tunsigned short int rt_irtt;\n};\n\n#define rt_mss\trt_mtu\n\n\nstruct in6_rtmsg {\n\tstruct in6_addr rtmsg_dst;\n\tstruct in6_addr rtmsg_src;\n\tstruct in6_addr rtmsg_gateway;\n\tuint32_t rtmsg_type;\n\tuint16_t rtmsg_dst_len;\n\tuint16_t rtmsg_src_len;\n\tuint32_t rtmsg_metric;\n\tunsigned long int rtmsg_info;\n\tuint32_t rtmsg_flags;\n\tint rtmsg_ifindex;\n};\n\n\n#define\tRTF_UP\t\t0x0001\n#define\tRTF_GATEWAY\t0x0002\n\n#define\tRTF_HOST\t0x0004\n#define RTF_REINSTATE\t0x0008\n#define\tRTF_DYNAMIC\t0x0010\n#define\tRTF_MODIFIED\t0x0020\n#define RTF_MTU\t\t0x0040\n#define RTF_MSS\t\tRTF_MTU\n#define RTF_WINDOW\t0x0080\n#define RTF_IRTT\t0x0100\n#define RTF_REJECT\t0x0200\n#define\tRTF_STATIC\t0x0400\n#define\tRTF_XRESOLVE\t0x0800\n#define RTF_NOFORWARD   0x1000\n#define RTF_THROW\t0x2000\n#define RTF_NOPMTUDISC  0x4000\n\n#define RTF_DEFAULT\t0x00010000\n#define RTF_ALLONLINK\t0x00020000\n#define RTF_ADDRCONF\t0x00040000\n\n#define RTF_LINKRT\t0x00100000\n#define RTF_NONEXTHOP\t0x00200000\n\n#define RTF_CACHE\t0x01000000\n#define RTF_FLOW\t0x02000000\n#define RTF_POLICY\t0x04000000\n\n#define RTCF_VALVE\t0x00200000\n#define RTCF_MASQ\t0x00400000\n#define RTCF_NAT\t0x00800000\n#define RTCF_DOREDIRECT 0x01000000\n#define RTCF_LOG\t0x02000000\n#define RTCF_DIRECTSRC\t0x04000000\n\n#define RTF_LOCAL\t0x80000000\n#define RTF_INTERFACE\t0x40000000\n#define RTF_MULTICAST\t0x20000000\n#define RTF_BROADCAST\t0x10000000\n#define RTF_NAT\t\t0x08000000\n\n#define RTF_ADDRCLASSMASK\t0xF8000000\n#define RT_ADDRCLASS(flags)\t((uint32_t) flags >> 23)\n\n#define RT_TOS(tos)\t\t((tos) & IPTOS_TOS_MASK)\n\n#define RT_LOCALADDR(flags)\t((flags & RTF_ADDRCLASSMASK) \\\n\t\t\t\t == (RTF_LOCAL|RTF_INTERFACE))\n\n#define RT_CLASS_UNSPEC\t\t0\n#define RT_CLASS_DEFAULT\t253\n\n#define RT_CLASS_MAIN\t\t254\n#define RT_CLASS_LOCAL\t\t255\n#define RT_CLASS_MAX\t\t255\n\n\n#define RTMSG_ACK\t\tNLMSG_ACK\n#define RTMSG_OVERRUN\t\tNLMSG_OVERRUN\n\n#define RTMSG_NEWDEVICE\t\t0x11\n#define RTMSG_DELDEVICE\t\t0x12\n#define RTMSG_NEWROUTE\t\t0x21\n#define RTMSG_DELROUTE\t\t0x22\n#define RTMSG_NEWRULE\t\t0x31\n#define RTMSG_DELRULE\t\t0x32\n#define RTMSG_CONTROL\t\t0x40\n\n#define RTMSG_AR_FAILED\t\t0x51\n#endif\n"
  },
  {
    "path": "kernel/nrf51/Kconfig",
    "content": "if ARCH_NRF51\n\nchoice\n    prompt \"MCU\"\n    default ARCH_NRF51822_QFAC\n\nconfig ARCH_NRF51822_QFAA\n    bool \"NRF51822_QFAA 256KB/16KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_16KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_QFAB\n    bool \"NRF51822_QFAB 128KB/16KB\"\n    select FLASH_SIZE_128KB\n    select RAM_SIZE_16KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_CEAA\n    bool \"NRF51822_CEAA 256KB/16KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_16KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_QFAC\n    bool \"NRF51822_QFAC 256KB/32KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_32KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_CDAB\n    bool \"NRF51822_CDAB 128KB/16KB\"\n    select FLASH_SIZE_128KB\n    select RAM_SIZE_16KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_CEAA\n    bool \"NRF51822_CEAA 256KB/16KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_16KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_CFAC\n    bool \"NRF51822_CFAC 256KB/32KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_32KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_CTAC\n    bool \"NRF51822_CTAC 256KB/32KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_32KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_CTAA\n    bool \"NRF51822_CTAA 256KB/16KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_16KB\n    select ARCH_NRF51822\nconfig ARCH_NRF51822_WFAC\n    bool \"NRF51822_WFAC 256KB/32KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_32KB\n    select ARCH_NRF51822\nendchoice\n\nendif\n"
  },
  {
    "path": "kernel/nrf51/blenanov1_5.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Roel Postelmans\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/nrf/51/uart.h\"\n#include <unicore-mx/nrf/51/gpio.h>\n#include \"gpio.h\"\n#include \"uart.h\"\n\n\nstatic const struct gpio_config Led0 = {\n    .base=GPIO,\n    .pin=GPIO19,\n    .mode=GPIO_DIR_OUTPUT,\n    .name=\"led0\"\n};\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_DEVUART\n#ifdef CONFIG_UART_0\n    {\n        .devidx = 0,\n        .base = UART0,\n        .irq = NVIC_UART0_IRQ,\n        .baudrate = UART_BAUD_115200,\n        .stop_bits = 1,\n        .data_bits = 8,\n        .parity = 0,\n        .flow = 0,\n        .pio_tx = {\n            .base=GPIO,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_INPUT,\n        },\n        .pio_rx = {\n            .base=GPIO,\n            .pin=GPIO11,\n            .mode=GPIO_MODE_OUTPUT,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n    },\n#endif\n#endif\n};\n\nint machine_init(void)\n{\n    gpio_create(NULL, &Led0);\n    uart_create(&uart_configs[0]);\n\n    return 0;\n}\n"
  },
  {
    "path": "kernel/nrf51/nrf51.ld.in",
    "content": "MEMORY\n{\n    FLASH (rx) : ORIGIN = __FLASH_ORIGIN, LENGTH = __KFLASHMEM_SIZE\n    SRAM (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __KRAMMEM_SIZE\n    SRAM_USER (rwx) : ORIGIN = (__RAM1_BASE + __KRAMMEM_SIZE), LENGTH = (__RAM1_SIZE - __KRAMMEM_SIZE)\n}\n\n /* Enforce emmition of the vector table. */\nEXTERN (vector_table)\n\n/* Define the entry point of the output file. */\nENTRY(reset_handler)\n\nSECTIONS\n{\n    .text :\n    {\n        KEEP(*(.vectors))\n        *(.text*)\n        *(.rodata*)\n    } > FLASH\n\t/* C++ Static constructors/destructors, also used for __attribute__\n\t * ((constructor)) and the likes */\n\t.preinit_array : {\n\t\t. = ALIGN(4);\n\t\t__preinit_array_start = .;\n\t\tKEEP (*(.preinit_array))\n\t\t__preinit_array_end = .;\n\t} > FLASH\n\t.init_array : {\n\t\t. = ALIGN(4);\n\t\t__init_array_start = .;\n\t\tKEEP (*(SORT(.init_array.*)))\n\t\tKEEP (*(.init_array))\n\t\t__init_array_end = .;\n\t} > FLASH\n\t.fini_array : {\n\t\t. = ALIGN(4);\n\t\t__fini_array_start = .;\n\t\tKEEP (*(.fini_array))\n\t\tKEEP (*(SORT(.fini_array.*)))\n\t\t__fini_array_end = .;\n\t} > FLASH\n \n    .data :\n    {\n        _etext = LOADADDR(.data);\n        _data = .;\n        *(vtable)\n        *(.data*)\n        _edata = .;\n    } > SRAM AT > FLASH\n\t_data_loadaddr = LOADADDR(.data);\n \n    .bss :\n    {\n        _bss = .;\n        *(.bss*)\n        *(COMMON)\n        . = ALIGN(32 / 8);\n        _ebss = .;\n        PROVIDE (end = .);\n    } > SRAM\n\n    .heap :\n    {\n        /* heap starts after BSS */\n        PROVIDE(_heap_start = _ebss );\n    } > SRAM\n}\n\nPROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));\nPROVIDE(_user_heap_start = ORIGIN(SRAM_USER));\nPROVIDE(_user_heap_end = ORIGIN(SRAM_USER) + LENGTH(SRAM_USER));\n"
  },
  {
    "path": "kernel/nrf52/Kconfig",
    "content": "if ARCH_NRF52\n\nchoice\n    prompt \"MCU\"\n    default ARCH_NRF52832\n\nconfig ARCH_NRF52840\n    bool \"NRF52840 1MB/512KB\"\n    select FLASH_SIZE_1MB\n    select RAM_SIZE_512KB\nconfig ARCH_NRF52832\n    bool \"NRF52832 512KB/64KB\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_64KB\nconfig ARCH_NRF52810\n    bool \"NRF52810 192KB/24KB\"\n    select FLASH_SIZE_192KB\n    select RAM_SIZE_24KB\nendchoice\n\nendif\n"
  },
  {
    "path": "kernel/nrf52/blenanov2_0.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Roel Postelmans\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/nrf/52/uart.h\"\n#include <unicore-mx/nrf/52/gpio.h>\n#include \"gpio.h\"\n#include \"uart.h\"\n\n\nstatic const struct gpio_config Led0 = {\n    .base=GPIO,\n    .pin=GPIO11,\n    .mode=GPIO_DIR_OUTPUT,\n    .name=\"led0\"\n};\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_DEVUART\n#ifdef CONFIG_UART_0\n    {\n        .devidx = 0,\n        .base = UART0,\n        .irq = NVIC_UART0_IRQ,\n        .baudrate = UART_BAUD_115200,\n        .stop_bits = 1,\n        .data_bits = 8,\n        .parity = 0,\n        .flow = 0,\n        .pio_tx = {\n            .base=GPIO,\n            .pin=GPIO29,\n            .mode=GPIO_MODE_OUTPUT,\n        },\n        .pio_rx = {\n            .base=GPIO,\n            .pin=GPIO30,\n            .mode=GPIO_MODE_INPUT,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n    },\n#endif\n#endif\n};\n\nint machine_init(void)\n{\n    gpio_create(NULL, &Led0);\n    uart_create(&uart_configs[0]);\n\n\n    return 0;\n}\n"
  },
  {
    "path": "kernel/nrf52/nrf52.ld.in",
    "content": "MEMORY\n{\n    FLASH (rx) : ORIGIN = __FLASH_ORIGIN, LENGTH = __KFLASHMEM_SIZE\n    SRAM (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __KRAMMEM_SIZE\n    SRAM_USER (rwx) : ORIGIN = (__RAM1_BASE + __KRAMMEM_SIZE), LENGTH = (__RAM1_SIZE - __KRAMMEM_SIZE)\n}\n\n /* Enforce emmition of the vector table. */\nEXTERN (vector_table)\n\n/* Define the entry point of the output file. */\nENTRY(reset_handler)\n\nSECTIONS\n{\n    .text :\n    {\n        KEEP(*(.vectors))\n        *(.text*)\n        *(.rodata*)\n    } > FLASH\n\t/* C++ Static constructors/destructors, also used for __attribute__\n\t * ((constructor)) and the likes */\n\t.preinit_array : {\n\t\t. = ALIGN(4);\n\t\t__preinit_array_start = .;\n\t\tKEEP (*(.preinit_array))\n\t\t__preinit_array_end = .;\n\t} > FLASH\n\t.init_array : {\n\t\t. = ALIGN(4);\n\t\t__init_array_start = .;\n\t\tKEEP (*(SORT(.init_array.*)))\n\t\tKEEP (*(.init_array))\n\t\t__init_array_end = .;\n\t} > FLASH\n\t.fini_array : {\n\t\t. = ALIGN(4);\n\t\t__fini_array_start = .;\n\t\tKEEP (*(.fini_array))\n\t\tKEEP (*(SORT(.fini_array.*)))\n\t\t__fini_array_end = .;\n\t} > FLASH\n \n    .data :\n    {\n        _etext = LOADADDR(.data);\n        _data = .;\n        *(vtable)\n        *(.data*)\n        _edata = .;\n    } > SRAM AT > FLASH\n\t_data_loadaddr = LOADADDR(.data);\n \n    .bss :\n    {\n        _bss = .;\n        *(.bss*)\n        *(COMMON)\n        . = ALIGN(32 / 8);\n        _ebss = .;\n        PROVIDE (end = .);\n    } > SRAM\n\n    .heap :\n    {\n        /* heap starts after BSS */\n        PROVIDE(_heap_start = _ebss );\n    } > SRAM\n}\n\nPROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));\nPROVIDE(_user_heap_start = ORIGIN(SRAM_USER));\nPROVIDE(_user_heap_end = ORIGIN(SRAM_USER) + LENGTH(SRAM_USER));\n"
  },
  {
    "path": "kernel/null.h",
    "content": "#ifndef INC_NULL\n#define INC_NULL\n\nvoid devnull_init(struct fnode *dev);\n\n#endif\n\n"
  },
  {
    "path": "kernel/pico_port.h",
    "content": "#ifndef PICO_PORT_FROSTED_INCLUDED\n#define PICO_PORT_FROSTED_INCLUDED\n#define PICO_SUPPORT_MUTEX\n\n#ifdef FROSTED\n#include \"frosted.h\"\n#include \"string.h\"\n#include \"malloc.h\"\n#include \"locks.h\"\n#include \"kprintf.h\"\n\n\n\n#define pico_free(x) f_free(x)\n#define pico_zalloc(x) f_calloc(MEM_TCPIP, x, 1)\n\nstatic void *pico_mutex_init(void) {\n    return mutex_init();\n}\n\nstatic void pico_mutex_lock(void *m) {\n    mutex_lock((mutex_t *)m);\n}\n\nstatic void pico_mutex_unlock(void *m) {\n    mutex_unlock((mutex_t *)m);\n}\n\nstatic void pico_mutex_deinit(void *m) {\n    mutex_destroy((mutex_t *)m);\n}\n\n#define dbg kprintf\n\nstatic inline pico_time PICO_TIME_MS()\n{\n    return jiffies;\n}\n\nstatic inline pico_time PICO_TIME()\n{\n    return jiffies / 1000;\n}\n\nstatic inline void PICO_IDLE(void)\n{\n}\n\n#else\n\n#error \"file pico_port.h included, but no FROSTED define.\"\n\n#endif\n\n#endif\n"
  },
  {
    "path": "kernel/pipe.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera\n *\n */\n\n#include \"frosted.h\"\n#include \"scheduler.h\"\n#include \"cirbuf.h\"\n#include \"string.h\"\n#include \"sys/termios.h\"\n#include \"poll.h\"\n\n#ifdef CONFIG_PIPE\n#define PIPE_BUFSIZE 64\n\nstatic struct module mod_pipe;\n\n\nstruct pipe_priv {\n    struct fnode *fno_r;\n    struct fnode *fno_w;\n    struct task *task_r;\n    struct task *task_w;\n    int w_off;\n    struct cirbuf *cb;\n};\n\nstatic struct fnode PIPE_ROOT = {\n};\n\n\nint sys_pipe2_hdlr(int paddr, int flags)\n{\n    int *pfd = (int*)paddr;\n    struct fnode *rd, *wr;\n    struct pipe_priv *pp;\n\n\n    if (task_ptr_valid(pfd))\n        return -EACCES;\n\n    pp = kalloc(sizeof (struct pipe_priv));\n    if (!pp) {\n        return -ENOMEM;\n    }\n\n    rd = fno_create(&mod_pipe, \"\", &PIPE_ROOT);\n    if (!rd) {\n        goto fail_rd;\n    }\n    wr = fno_create(&mod_pipe, \"\", &PIPE_ROOT);\n    if (!wr) {\n        goto fail_wr;\n    }\n\n    pfd[0] = task_filedesc_add(rd);\n    pfd[1] = task_filedesc_add(wr);\n\n    if (pfd[0] < 0 || pfd[1] < 0) {\n        goto fail_all;\n    }\n\n    task_fd_setmask(pfd[0], O_RDONLY);\n    task_fd_setmask(pfd[1], O_WRONLY);\n\n    rd->priv = pp;\n    wr->priv = pp;\n\n    pp->fno_r = rd;\n    pp->fno_w = wr;\n    pp->task_r = NULL;\n    pp->task_w = NULL;\n    pp->w_off = 0;\n    pp->cb = cirbuf_create(PIPE_BUFSIZE);\n    if (!pp->cb) {\n        goto fail_all;\n    }\n    return 0;\n\nfail_all:\n        fno_unlink(wr);\nfail_wr:\n        fno_unlink(rd);\nfail_rd:\n        kfree(pp);\n        return -ENOMEM;\n\n}\n\nstatic int pipe_poll(struct fnode *f, uint16_t events, uint16_t *revents)\n{\n    struct pipe_priv *pp;\n    if (f->owner != &mod_pipe)\n        return -EINVAL;\n    pp = (struct pipe_priv *)f->priv;\n    if (!pp) {\n        return -EINVAL;\n    }\n\n    if (f == pp->fno_w) {\n        if(pp->fno_r == 0) {\n            *revents |= POLLHUP;\n            return 1;\n        }\n        else if ((events & POLLOUT) && (cirbuf_bytesfree(pp->cb) > 0)) {\n            *revents = POLLOUT;\n            return 1;\n        }\n    }\n\n    if ((f == pp->fno_r) && (events & POLLIN) && (cirbuf_bytesinuse(pp->cb) > 0)) {\n        *revents |= POLLIN;\n        return 1;\n    }\n    return 0;\n}\n\n\nstatic int pipe_close(struct fnode *f)\n{\n    struct pipe_priv *pp;\n    struct task *t;\n    t = this_task();\n    if (!f)\n        return -EINVAL;\n\n    if (f->owner != &mod_pipe)\n        return -EINVAL;\n\n    pp = (struct pipe_priv *)f->priv;\n    if (!pp)\n        return -EINVAL;\n\n\n    if (f == pp->fno_r) {\n        pp->fno_r = NULL;\n        fno_unlink(f);\n        if ((pp->task_w != t) && (pp->task_w != NULL)) {\n            task_resume(pp->task_w);\n        }\n    }\n    if (f == pp->fno_w) {\n        pp->fno_w = NULL;\n        fno_unlink(f);\n        if ((pp->task_r != t) && (pp->task_r != NULL)) {\n            task_resume(pp->task_r);\n        }\n    }\n    if ((!pp->fno_w) && (!pp->fno_r))\n        kfree(pp);\n    return 0;\n}\n\nstatic int pipe_read(struct fnode *f, void *buf, unsigned int len)\n{\n    struct pipe_priv *pp;\n    int out, len_available;\n    uint8_t *ptr = buf;\n\n    if (f->owner != &mod_pipe)\n        return -EINVAL;\n\n    pp = (struct pipe_priv *)f->priv;\n    if (!pp)\n        return -EINVAL;\n\n    if (pp->fno_r != f)\n        return -EPERM;\n\n    len_available =  cirbuf_bytesinuse(pp->cb);\n    if (len_available <= 0) {\n        if (FNO_BLOCKING(f)) {\n            pp->task_r = this_task();\n            task_suspend();\n            return SYS_CALL_AGAIN;\n        } else {\n            return -EWOULDBLOCK;\n        }\n    }\n\n    for(out = 0; out < len; out++) {\n        /* read data */\n        if (cirbuf_readbyte(pp->cb, ptr) != 0)\n            break;\n        ptr++;\n    }\n    pp->task_r = 0;\n    return out;\n}\n\nstatic int pipe_write(struct fnode *f, const void *buf, unsigned int len)\n{\n    struct pipe_priv *pp;\n    int out, len_available;\n    const uint8_t *ptr = buf;\n\n    if (f->owner != &mod_pipe)\n        return -EINVAL;\n\n    pp = (struct pipe_priv *)f->priv;\n    if (!pp)\n        return -EINVAL;\n\n    if (pp->fno_w != f)\n        return -EPERM;\n\n    out = pp->w_off;\n\n    len_available =  cirbuf_bytesfree(pp->cb);\n    if (len_available > (len - out))\n        len_available = (len - out);\n    for(; out < len_available; out++) {\n        /* write data */\n        if (cirbuf_writebyte(pp->cb, *(ptr + out)) != 0)\n            break;\n    }\n\n    if (out < len) {\n        if (FNO_BLOCKING(f)) {\n            pp->task_w = this_task();\n            pp->w_off = out;\n            task_suspend();\n            return SYS_CALL_AGAIN;\n        } else {\n            if (out == 0)\n                return -EWOULDBLOCK;\n        }\n    }\n    pp->w_off = 0;\n    pp->task_w = NULL;\n    return out;\n}\n\nvoid sys_pipe_init(void)\n{\n    mod_pipe.family = FAMILY_DEV;\n    strcpy(mod_pipe.name,\"pipe\");\n    mod_pipe.ops.poll = pipe_poll;\n    mod_pipe.ops.close = pipe_close;\n    mod_pipe.ops.read = pipe_read;\n    mod_pipe.ops.write = pipe_write;\n\n\n    register_module(&mod_pipe);\n}\n#else\n#   define sys_pipe_init()  do{}while(0)\nint sys_pipe2_hdlr(int paddr, int flags) {\n    return -ENOSYS;\n}\n#endif\n"
  },
  {
    "path": "kernel/scheduler.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent, Antonio Cardace, brabo\n *\n */\n#include \"frosted.h\"\n#include \"sys/frosted.h\"\n#include \"string.h\" /* flibc string.h */\n#include \"signal.h\"\n#include \"kprintf.h\"\n#include \"sys/wait.h\"\n#include \"vfs.h\"\n#include \"sys/pthread.h\"\n#include \"fpb.h\"\n#include \"poll.h\"\n#include \"lowpower.h\"\n\n#include \"sys/user.h\"\n\n\n#define __inl inline\n#define __naked __attribute__((naked))\n\n/* Full kernel space separation */\n#define RUN_HANDLER (0xfffffff1u)\n#define MSP \"msp\"\n#define PSP \"psp\"\n#define RUN_KERNEL (0xfffffff9u)\n#define RUN_USER (0xfffffffdu)\n\n#define SV_CALL_SIGRETURN 0xFFFFFFF8\n#define STACK_THRESHOLD 64\n\n/* TOP to Bottom: EXTRA | NVIC | T_EXTRA | T_NVIC */\nvolatile struct extra_stack_frame *cur_extra;\nvolatile struct nvic_stack_frame *cur_nvic;\nvolatile struct extra_stack_frame *tramp_extra;\nvolatile struct nvic_stack_frame *tramp_nvic;\nvolatile struct extra_stack_frame *extra_usr;\n\nint task_ptr_valid(const void *ptr);\n\n#ifdef CONFIG_SYSCALL_TRACE\n#define STRACE_SIZE 10\nstruct strace {\n    int pid;\n    int n;\n    uint32_t sp;\n};\n\nvolatile struct strace Strace[STRACE_SIZE];\nvolatile int StraceTop = 0;\n#endif\n\n#ifdef CONFIG_EXTENDED_MEMFAULT\nstatic char _my_x_str[11] = \"\";\nstatic char *x_str(uint32_t x)\n{\n    int i;\n    uint8_t val;\n    _my_x_str[0] = '0';\n    _my_x_str[1] = 'x';\n    for (i = 0; i < 8; i++) {\n        val = (((x >> ((7 - i) << 2)) & 0x0000000F));\n        if (val < 10)\n            _my_x_str[i + 2] = val + '0';\n        else\n            _my_x_str[i + 2] = (val - 10) + 'A';\n    }\n    _my_x_str[10] = 0;\n    return _my_x_str;\n}\n\nstatic char _my_pid_str[6];\nstatic char *pid_str(uint16_t p)\n{\n    int i = 0;\n    if (p >= 10000) {\n        _my_pid_str[i++] = (p / 10000) + '0';\n        p = p % 10000;\n    }\n    if (i > 0 || p >= 1000) {\n        _my_pid_str[i++] = (p / 1000) + '0';\n        p = p % 1000;\n    }\n    if (i > 0 || p >= 100) {\n        _my_pid_str[i++] = (p / 100) + '0';\n        p = p % 100;\n    }\n    if (i > 0 || p >= 10) {\n        _my_pid_str[i++] = (p / 10) + '0';\n        p = p % 10;\n    }\n    _my_pid_str[i++] = p + '0';\n    _my_pid_str[i] = 0;\n    return _my_pid_str;\n}\n#endif\n\n/* Array of syscalls */\nstatic void *sys_syscall_handlers[_SYSCALLS_NR] = {\n\n};\n\nint sys_register_handler(uint32_t n, int (*_sys_c)(uint32_t arg1, uint32_t arg2,\n                                                   uint32_t arg3, uint32_t arg4,\n                                                   uint32_t arg5))\n{\n    if (n >= _SYSCALLS_NR)\n        return -1; /* Attempting to register non-existing syscall */\n\n    if (sys_syscall_handlers[n] != NULL)\n        return -1; /* Syscall already registered */\n\n    sys_syscall_handlers[n] = _sys_c;\n    return 0;\n}\n\n#define MAX_TASKS 16\n#define BASE_TIMESLICE (20)\n\n#define TIMESLICE(x) ((BASE_TIMESLICE) - ((x)->tb.nice >> 1))\n#define SCHEDULER_STACK_SIZE                                                   \\\n    ((CONFIG_TASK_STACK_SIZE - sizeof(struct task_block)) - F_MALLOC_OVERHEAD)\n#define INIT_SCHEDULER_STACK_SIZE (256)\n\nstruct __attribute__((packed)) nvic_stack_frame {\n    uint32_t r0;\n    uint32_t r1;\n    uint32_t r2;\n    uint32_t r3;\n    uint32_t r12;\n    uint32_t lr;\n    uint32_t pc;\n    uint32_t psr;\n#if (__CORTEX_M == 4) /* CORTEX-M4 saves FPU frame as well */\n    uint32_t s0;\n    uint32_t s1;\n    uint32_t s2;\n    uint32_t s3;\n    uint32_t s4;\n    uint32_t s5;\n    uint32_t s6;\n    uint32_t s7;\n    uint32_t s8;\n    uint32_t s9;\n    uint32_t s10;\n    uint32_t s11;\n    uint32_t s12;\n    uint32_t s13;\n    uint32_t s14;\n    uint32_t s15;\n    uint32_t fpscr;\n    uint32_t dummy;\n#endif\n};\n/* In order to keep the code efficient, the stack layout of armv6 and armv7 do NOT match! */\nstruct __attribute__((packed)) extra_stack_frame {\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    uint32_t r4;\n    uint32_t r5;\n    uint32_t r6;\n    uint32_t r7;\n    uint32_t r8;\n    uint32_t r9;\n    uint32_t r10;\n    uint32_t r11;\n#elif defined(__ARM_ARCH_6M__)\n    uint32_t r8;\n    uint32_t r9;\n    uint32_t r10;\n    uint32_t r11;\n    uint32_t r4;\n    uint32_t r5;\n    uint32_t r6;\n    uint32_t r7;\n#endif\n};\n\n#define NVIC_FRAME_SIZE ((sizeof(struct nvic_stack_frame)))\n#define EXTRA_FRAME_SIZE ((sizeof(struct extra_stack_frame)))\n\nstatic void *_top_stack;\n#define TASK_FLAG_VFORK 0x01\n#define TASK_FLAG_IN_SYSCALL 0x02\n#define TASK_FLAG_SIGNALED 0x04\n#define TASK_FLAG_INTR 0x40\n#define TASK_FLAG_SYSCALL_STOP 0x80\n/* thread related */\n#define TASK_FLAG_DETACHED 0x0100\n#define TASK_FLAG_CANCELABLE 0x0200\n#define TASK_FLAG_PENDING_CANC 0x0400\n/* Timer expired */\n#define TASK_FLAG_TIMEOUT 0x0800\n\nstruct filedesc {\n    struct fnode *fno;\n    uint32_t off;\n    uint32_t mask;\n    uint32_t flags;\n};\n\nstruct filedesc_table {\n    uint32_t n_files;\n    uint32_t usage_count;\n    struct filedesc *fdesc;\n};\n\nstruct task_handler {\n    int signo;\n    void (*hdlr)(int);\n    uint32_t mask;\n    struct task_handler *next;\n};\n\n#ifdef CONFIG_PTHREADS\nstruct thread_group {\n    struct task **threads;\n    uint16_t active_threads;\n    uint16_t n_threads;\n    uint16_t max_tid;\n    pthread_key_t max_key;\n};\n#else\nstruct thread_group {\n    uint32_t _off;\n};\n#endif\nstatic void destroy_thread_group(struct thread_group *group, uint16_t tid);\n\n\nstruct __attribute__((packed)) task_block {\n    /* Watch out for alignment here\n     * (try to pack togehter smaller fields)\n     * */\n    void (*start)(void *);\n    void *arg;\n\n    uint16_t flags;\n    uint8_t state;\n    int8_t nice;\n\n    uint16_t timeslice;\n    uint16_t pid;\n\n    uint16_t ppid;\n    uint16_t tid;\n    uint16_t joiner_thread_tid;\n    uint16_t _padding;\n    struct thread_group *tgroup;\n    struct task *tracer;\n    int exitval;\n    struct fnode *cwd;\n    struct task_handler *sighdlr;\n    sigset_t sigmask;\n    sigset_t sigpend;\n    struct filedesc_table *filedesc_table;\n    void *sp;\n    void *osp;\n    void *cur_stack;\n    struct task *next;\n    struct vfs_info *vfsi;\n    int timer_id;\n    uint32_t *specifics;\n    uint32_t n_specifics;\n};\n\nstruct __attribute__((packed)) task {\n    struct task_block tb;\n    uint32_t stack[SCHEDULER_STACK_SIZE / 4];\n};\n\nstatic struct task struct_task_kernel;\nstatic struct task *const kernel = (struct task *)(&struct_task_kernel);\n\nstatic int number_of_tasks = 0;\n\nstatic void tasklist_add(struct task **list, struct task *el)\n{\n    el->tb.next = *list;\n    *list = el;\n}\n\nstatic int tasklist_del(struct task **list, struct task *togo)\n{\n    struct task *t = *list;\n    struct task *p = NULL;\n\n    while (t) {\n        if (t == togo) {\n            if (p == NULL)\n                *list = t->tb.next;\n            else\n                p->tb.next = t->tb.next;\n            return 0;\n        }\n        p = t;\n        t = t->tb.next;\n    }\n    return -1;\n}\n\nstatic int tasklist_len(struct task **list)\n{\n    struct task *t = *list;\n    struct task *p = NULL;\n    int len = 0;\n    while (t) {\n        len++;\n        t = t->tb.next;\n    }\n    return len;\n}\n\nstatic struct task *tasklist_get(struct task **list, uint16_t pid)\n{\n    struct task *t = *list;\n    while (t) {\n        if ((t->tb.pid == pid) && (t->tb.tid == 1))\n            return t;\n        t = t->tb.next;\n    }\n    return NULL;\n}\n\nstatic struct task *tasks_running = NULL;\nstatic struct task *tasks_idling = NULL;\nvoid task_resume(struct task *t);\nvoid task_resume_lock(struct task *t);\nvoid task_stop(struct task *t);\nvoid task_continue(struct task *t);\nvoid task_terminate(struct task *t);\nstatic void task_suspend_to(int newstate);\nvoid task_deliver_sigchld(void *arg);\nvoid task_deliver_sigtrap(void *arg);\n\nstatic void ftable_destroy(struct task *t);\nstatic void idling_to_running(struct task *t)\n{\n    if (tasklist_del(&tasks_idling, t) == 0)\n        tasklist_add(&tasks_running, t);\n}\n\nstatic void running_to_idling(struct task *t)\n{\n    if ((t->tb.pid < 1) && (t->tb.tid <= 1))\n        return;\n    if (tasklist_del(&tasks_running, t) == 0)\n        tasklist_add(&tasks_idling, t);\n}\n\nstatic int task_filedesc_del_from_task(struct task *t, int fd);\n\n\n/* Catch-all destroy functions for processes and threads.\n *\n * Single point of deallocation for all the memory related\n * to task management.\n */\nstatic void task_destroy(void *arg)\n{\n    struct task *t = arg;\n    int i;\n    struct filedesc_table *ft;\n    struct thread_group *grp;\n    if (!t)\n        return;\n    tasklist_del(&tasks_running, t);\n    tasklist_del(&tasks_idling, t);\n#ifdef CONFIG_PTHREADS\n    grp = t->tb.tgroup;\n    if ((grp) && (grp->active_threads > 0)) {\n        /* if single sub-thread being destroyed, delete from\n         * the group->threads array, so the position can\n         * be reused.\n         *\n         * We never get here after a destroy_thread_group()\n         * that has been called by the leader, because t->group\n         * has been set to NULL.\n         */\n        for (i = 0; i < grp->n_threads; i++) {\n            if (grp->threads[i] == t) {\n                grp->threads[i] = NULL;\n            }\n        }\n    } else {\n        /* Last (or the one) thread in group being destroyed. Free resources. */\n        if (grp)\n            destroy_thread_group(grp, t->tb.tid);\n        /* Get rid of allocated arguments */\n        if (t->tb.arg) {\n            char **arg = (char **)(t->tb.arg);\n            i = 0;\n            while (arg[i]) {\n                f_free(arg[i]);\n                i++;\n            }\n        }\n        f_free(t->tb.arg);\n        /* Close files & Destroy the file table */\n        ft = t->tb.filedesc_table;\n        for (i = 0; (ft) && (i < ft->n_files); i++) {\n            task_filedesc_del_from_task(t, i);\n        }\n        ftable_destroy(t);\n        /* free allocated VFS mem, e.g. by bflt_load */\n        if (t->tb.vfsi) {\n            // kprintf(\"Freeing VFS type %d allocated pointer 0x%p\\r\\n\",\n            // t->tb.vfsi->type, t->tb.vfsi->allocated);\n            if ((t->tb.vfsi->type == VFS_TYPE_BFLT) && (t->tb.vfsi->allocated))\n                f_free(t->tb.vfsi->allocated);\n            f_free(t->tb.vfsi);\n        }\n        /* free pre-allocated thread space */\n        if (grp) {\n            kfree(grp->threads);\n            kfree(grp);\n            t->tb.tgroup = NULL;\n        }\n        /* Remove heap allocations spawned by this pid. */\n        f_proc_heap_free(t->tb.pid);\n    }\n    /* Free any pthread-specific key value */\n    if (t->tb.specifics)\n        kfree(t->tb.specifics);\n#else\n    /* Get rid of allocated arguments */\n    if (t->tb.arg) {\n        char **arg = (char **)(t->tb.arg);\n        i = 0;\n        while (arg[i]) {\n            f_free(arg[i]);\n            i++;\n        }\n    }\n    f_free(t->tb.arg);\n    /* Close files & Destroy the file table */\n    ft = t->tb.filedesc_table;\n    for (i = 0; (ft) && (i < ft->n_files); i++) {\n        task_filedesc_del_from_task(t, i);\n    }\n    ftable_destroy(t);\n    /* free allocated VFS mem, e.g. by bflt_load */\n    if (t->tb.vfsi) {\n        // kprintf(\"Freeing VFS type %d allocated pointer 0x%p\\r\\n\",\n        // t->tb.vfsi->type, t->tb.vfsi->allocated);\n        if ((t->tb.vfsi->type == VFS_TYPE_BFLT) && (t->tb.vfsi->allocated))\n            f_free(t->tb.vfsi->allocated);\n        f_free(t->tb.vfsi);\n    }\n    /* Remove heap allocations spawned by this pid. */\n    f_proc_heap_free(t->tb.pid);\n#endif\n    /* Get rid of stack space allocation, timer. */\n    if (t->tb.timer_id >= 0)\n        ktimer_del(t->tb.timer_id);\n    task_space_free(t);\n    number_of_tasks--;\n}\n\nstatic struct task *_cur_task = NULL;\nstatic struct task *forced_task = NULL;\n\nstatic __inl int in_kernel(void)\n{\n    return ((_cur_task->tb.pid == 0) && (_cur_task->tb.tid <= 1));\n}\n\nstruct task *this_task(void)\n{\n    /* External modules like locks.c expect this to\n     * return NULL when in kernel\n     */\n    if (in_kernel())\n        return NULL;\n    return _cur_task;\n}\n\nint task_get_timer_id(void)\n{\n    return _cur_task->tb.timer_id;\n}\n\nvoid task_set_timer_id(int id)\n{\n    _cur_task->tb.timer_id = id;\n}\n\nint task_in_syscall(void)\n{\n    return ((_cur_task->tb.flags & TASK_FLAG_IN_SYSCALL) ==\n            TASK_FLAG_IN_SYSCALL);\n}\n\nstatic int next_pid(void)\n{\n    static unsigned int next_available = 0;\n    uint16_t ret = (uint16_t)((next_available)&0xFFFF);\n    next_available++;\n    if (next_available > 0xFFFF) {\n        next_available = 2;\n    }\n    while (tasklist_get(&tasks_idling, next_available) ||\n           tasklist_get(&tasks_running, next_available))\n        next_available++;\n    return ret;\n}\n\n/********************************/\n/* Handling of file descriptors */\n/********************************/\n/********************************/\n/********************************/\n/**/\n/**/\n/**/\n\nstatic struct filedesc_table *ftable_create(struct task *t)\n{\n    struct filedesc_table *ft = t->tb.filedesc_table;\n    if (ft)\n        return ft;\n    ft = kcalloc(sizeof(struct filedesc_table), 1);\n    if (!ft)\n        return NULL;\n    ft->usage_count = 1;\n    t->tb.filedesc_table = ft;\n    return ft;\n}\n\nstatic void ftable_destroy(struct task *t)\n{\n    struct filedesc_table *ft = t->tb.filedesc_table;\n    if (ft) {\n        if (--ft->usage_count == 0) {\n            if (ft->fdesc)\n                kfree(ft->fdesc);\n            kfree(ft);\n        }\n    }\n    t->tb.filedesc_table = NULL;\n}\n\nstatic int task_filedesc_add_to_task(struct task *t, struct fnode *f)\n{\n    int i;\n    void *re;\n    struct filedesc_table *ft = t->tb.filedesc_table;\n    if (!t || !f)\n        return -EINVAL;\n\n    if (!ft)\n        ft = ftable_create(t);\n\n    for (i = 0; i < ft->n_files; i++) {\n        if (ft->fdesc[i].fno == NULL) {\n            f->usage_count++;\n            ft->fdesc[i].fno = f;\n            return i;\n        }\n    }\n    ft->n_files++;\n    re = (void *)krealloc(ft->fdesc, ft->n_files * sizeof(struct filedesc));\n    if (!re)\n        return -1;\n    ft->fdesc = re;\n    memset(&(ft->fdesc[ft->n_files - 1]), 0, sizeof(struct filedesc));\n    ft->fdesc[ft->n_files - 1].fno = f;\n    if (f->flags & FL_TTY) {\n        struct module *mod = f->owner;\n        if (mod && mod->ops.tty_attach) {\n            mod->ops.tty_attach(f, t->tb.pid);\n        }\n    }\n    f->usage_count++;\n    return ft->n_files - 1;\n}\n\nint task_filedesc_add(struct fnode *f)\n{\n    return task_filedesc_add_to_task(_cur_task, f);\n}\n\nstatic int task_filedesc_del_from_task(struct task *t, int fd)\n{\n    struct fnode *fno;\n    struct filedesc_table *ft;\n    if (!t)\n        return -EINVAL;\n\n    ft = t->tb.filedesc_table;\n    fno = ft->fdesc[fd].fno;\n    if (!fno)\n        return -ENOENT;\n\n    /* Reattach controlling tty to parent task */\n    if ((fno->flags & FL_TTY) && ((ft->fdesc[fd].mask & O_NOCTTY) == 0)) {\n        struct module *mod = fno->owner;\n        if (mod && mod->ops.tty_attach) {\n            mod->ops.tty_attach(fno, t->tb.ppid);\n        }\n    }\n\n    /* If this was the last user of the file, close it. */\n    fno->usage_count--;\n    if (fno->usage_count <= 0) {\n        if (fno->owner && fno->owner->ops.close)\n            fno->owner->ops.close(fno);\n    }\n    ft->fdesc[fd].fno = NULL;\n}\n\nint task_filedesc_del(int fd)\n{\n    return task_filedesc_del_from_task(_cur_task, fd);\n}\n\nint task_fd_setmask(int fd, uint32_t mask)\n{\n    struct filedesc_table *ft;\n    struct fnode *fno;\n\n    ft = _cur_task->tb.filedesc_table;\n\n    if (!ft)\n        return -EINVAL;\n\n    if (fd < 0 || fd > ft->n_files)\n        return -ENOENT;\n\n    fno = ft->fdesc[fd].fno;\n    if (!fno)\n        return -ENOENT;\n\n    if ((mask & O_ACCMODE) != O_RDONLY) {\n        if ((fno->flags & FL_WRONLY) == 0)\n            return -EPERM;\n    }\n    ft->fdesc[fd].mask = mask;\n    return 0;\n}\n\nuint32_t task_fd_getmask(int fd)\n{\n    struct filedesc_table *ft;\n    ft = _cur_task->tb.filedesc_table;\n    if (fd < 0 || fd > ft->n_files)\n        return 0;\n    if (ft->fdesc[fd].fno)\n        return ft->fdesc[fd].mask;\n    return 0;\n}\n\nuint32_t task_fd_set_flags(int fd, uint32_t flags)\n{\n    struct filedesc_table *ft;\n    struct fnode *fno;\n\n    ft = _cur_task->tb.filedesc_table;\n\n    if (!ft)\n        return -EINVAL;\n\n    if (fd < 0 || fd > ft->n_files)\n        return -ENOENT;\n\n    fno = ft->fdesc[fd].fno;\n    if (!fno)\n        return -ENOENT;\n\n    ft->fdesc[fd].flags = flags;\n    return 0;\n}\n\nuint32_t task_fd_get_flags(int fd)\n{\n    struct fnode *fno;\n    struct filedesc_table *ft;\n    struct filedesc *fdesc;\n    ft = _cur_task->tb.filedesc_table;\n    if (!ft)\n        return -EINVAL;\n\n    if (fd < 0 || fd > ft->n_files)\n        return -ENOENT;\n\n    fdesc = &ft->fdesc[fd];\n    if (!fdesc)\n        return -ENOENT;\n    return fdesc->flags;\n}\n\nuint32_t task_fd_set_off(struct fnode *fno, uint32_t off)\n{\n    struct filedesc_table *ft;\n    struct filedesc *fdesc;\n    int fd;\n    int found = 0;\n    ft = _cur_task->tb.filedesc_table;\n    if (!ft)\n        return 0;\n\n    /* Set offset to all instances of the file in the ft */\n    for (fd = 0; fd < ft->n_files; fd++) {\n        if (ft->fdesc[fd].fno == fno) {\n            ft->fdesc[fd].off = off;\n            found++;\n        } \n    }\n    if (found)\n        return off;\n    return 0;\n}\n\nuint32_t task_fd_get_off(struct fnode *fno)\n{\n    struct filedesc_table *ft;\n    struct filedesc *fdesc;\n    int fd;\n    ft = _cur_task->tb.filedesc_table;\n    if (!ft)\n        return 0;\n\n    for (fd = 0; fd < ft->n_files; fd++) {\n        if (ft->fdesc[fd].fno == fno)\n            return ft->fdesc[fd].off;\n    }\n    return 0;\n}\n\nstruct fnode *task_filedesc_get(int fd)\n{\n    struct task *t = _cur_task;\n    struct filedesc_table *ft;\n    if (!t)\n        return NULL;\n    ft = t->tb.filedesc_table;\n    if (!ft)\n        return NULL;\n    if (fd < 0)\n        return NULL;\n    if (fd >= ft->n_files)\n        return NULL;\n    if ((ft->n_files - 1) < fd)\n        return NULL;\n    if (ft->fdesc[fd].fno == NULL)\n        return NULL;\n    return ft->fdesc[fd].fno;\n}\n\nint task_fd_readable(int fd)\n{\n    if (!task_filedesc_get(fd))\n        return 0;\n    return 1;\n}\n\nint task_fd_writable(int fd)\n{\n    if (!task_filedesc_get(fd))\n        return 0;\n    if ((_cur_task->tb.filedesc_table->fdesc[fd].mask & O_ACCMODE) == O_RDONLY)\n        return 0;\n    return 1;\n}\n\nint sys_dup_hdlr(int fd)\n{\n    struct task *t = _cur_task;\n    struct fnode *f = task_filedesc_get(fd);\n    int newfd = -1;\n    if (!f)\n        return -1;\n    newfd = task_filedesc_add(f);\n    if (newfd >= 0)\n        _cur_task->tb.filedesc_table->fdesc[newfd].mask =\n            _cur_task->tb.filedesc_table->fdesc[fd].mask;\n    return newfd;\n}\n\nint sys_dup2_hdlr(int fd, int newfd)\n{\n    struct task *t = _cur_task;\n    struct fnode *f = task_filedesc_get(fd);\n    struct filedesc_table *ft = t->tb.filedesc_table;\n\n    if (!ft)\n        return -1;\n    if (newfd < 0)\n        return -1;\n    if (newfd == fd)\n        return -1;\n    if (!f)\n        return -1;\n\n    /* TODO: create empty fnodes up until newfd */\n    if (newfd >= ft->n_files)\n        return -1;\n    if (ft->fdesc[newfd].fno != NULL)\n        task_filedesc_del(newfd);\n    ft->fdesc[newfd].fno = f;\n    return newfd;\n}\n\n/********************************/\n/*            Signals           */\n/********************************/\n/********************************/\n/********************************/\n/**/\n/**/\n/**/\n\n#ifdef CONFIG_SIGNALS\n\nstatic void sig_trampoline(struct task *t, struct task_handler *h, int signo);\nint sys_kill_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                  uint32_t arg5);\nstatic int catch_signal(struct task *t, int signo, sigset_t orig_mask)\n{\n    int i;\n    struct task_handler *sighdlr;\n    struct task_handler *h = NULL;\n\n    if (!t || (t->tb.pid < 1))\n        return -EINVAL;\n\n    if ((t->tb.state == TASK_ZOMBIE) || (t->tb.state == TASK_OVER) ||\n        (t->tb.state == TASK_FORKED))\n        return -ESRCH;\n\n    if (((1 << signo) & t->tb.sigmask) && (h->hdlr != SIG_IGN)) {\n        /* Signal is blocked via t->tb.sigmask */\n        t->tb.sigpend |= (1 << signo);\n        return 0;\n    }\n\n    /* If process is being traced, deliver SIGTRAP to tracer */\n    if (t->tb.tracer != NULL) {\n        tasklet_add(task_deliver_sigtrap, t->tb.tracer);\n    }\n\n    /* Reset signal, if pending, as it's going to be handled. */\n    t->tb.sigpend &= ~(1 << signo);\n\n    sighdlr = t->tb.sighdlr;\n    while (sighdlr) {\n        if (signo == sighdlr->signo)\n            h = sighdlr;\n        sighdlr = sighdlr->next;\n    }\n\n    if ((h) && (signo != SIGKILL) && (signo != SIGSEGV)) {\n        /* Handler is present */\n        if ((h->hdlr == NULL) || (h->hdlr == SIG_IGN))\n            return 0;\n\n        if (_cur_task == t) {\n            h->hdlr(signo);\n        } else {\n            sig_trampoline(t, h, signo);\n        }\n    } else {\n        /* Handler not present: SIG_DFL */\n        if (signo == SIGSTOP) {\n            task_stop(t);\n        } else if (signo == SIGCHLD) {\n            task_resume(t);\n        } else if (signo == SIGCONT) {\n            /* If not in stopped state, SIGCONT is ignored. */\n            task_continue(t);\n        } else {\n            task_terminate(t);\n        }\n    }\n    return 0;\n}\n\nstatic void check_pending_signals(struct task *t)\n{\n    int i;\n    t->tb.sigpend &= ~(t->tb.sigmask);\n    while (t->tb.sigpend != 0u) {\n        for (i = 1; i < SIGMAX; i++) {\n            if ((1 << i) & t->tb.sigpend)\n                catch_signal(t, i, t->tb.sigmask);\n        }\n    }\n}\n\nstatic int add_handler(struct task *t, int signo, void (*hdlr)(int),\n                       uint32_t mask)\n{\n    struct task_handler *sighdlr;\n    if (!t || (t->tb.pid < 1))\n        return -EINVAL;\n\n    sighdlr = kalloc(sizeof(struct task_handler));\n    if (!sighdlr)\n        return -ENOMEM;\n\n    sighdlr->signo = signo;\n    sighdlr->hdlr = hdlr;\n    sighdlr->mask = mask;\n    sighdlr->next = t->tb.sighdlr;\n    t->tb.sighdlr = sighdlr;\n    check_pending_signals(t);\n    return 0;\n}\n\nstatic int del_handler(struct task *t, int signo)\n{\n    struct task_handler *sighdlr;\n    struct task_handler *prev = NULL;\n    if (!t || (t->tb.pid < 1))\n        return -EINVAL;\n\n    sighdlr = t->tb.sighdlr;\n    while (sighdlr) {\n        if (sighdlr->signo == signo) {\n            if (prev == NULL) {\n                t->tb.sighdlr = sighdlr->next;\n            } else {\n                prev->next = sighdlr->next;\n            }\n            kfree(sighdlr);\n            check_pending_signals(t);\n            return 0;\n        }\n        prev = sighdlr;\n        sighdlr = sighdlr->next;\n    }\n    return -ESRCH;\n}\n\nstatic void sig_hdlr_return(uint32_t arg)\n{\n    /* XXX: In order to use per-sigaction sa_mask, we need to set\n     * t->tb.sigmask in the catch, and restore it here.\n     */\n\n    /* call special svc with n = SV_CALL_SIGRETURN */\n    asm volatile(\"mov r0, %0\" ::\"r\"(SV_CALL_SIGRETURN));\n    asm volatile(\"svc 0\\n\");\n    // asm volatile (\"pop {r4-r11}\\n\");\n}\n\nstatic void sig_trampoline(struct task *t, struct task_handler *h, int signo)\n{\n    cur_extra = t->tb.sp + NVIC_FRAME_SIZE + EXTRA_FRAME_SIZE;\n    cur_nvic = t->tb.sp + EXTRA_FRAME_SIZE;\n    tramp_extra = t->tb.sp - EXTRA_FRAME_SIZE;\n    tramp_nvic = t->tb.sp - (EXTRA_FRAME_SIZE + NVIC_FRAME_SIZE);\n    extra_usr = t->tb.sp;\n\n    /* Save stack pointer for later */\n    memcpy((void *)t->tb.sp, (void *)cur_extra, EXTRA_FRAME_SIZE);\n    t->tb.osp = t->tb.sp;\n\n    /* Copy the EXTRA_FRAME into the trampoline extra, to preserve R9 for\n     * userspace relocations etc. */\n    memcpy((void *)tramp_extra, (void *)cur_extra, EXTRA_FRAME_SIZE);\n\n    memset((void *)tramp_nvic, 0, NVIC_FRAME_SIZE);\n    tramp_nvic->pc = (uint32_t)h->hdlr;\n    tramp_nvic->lr = (uint32_t)sig_hdlr_return;\n    tramp_nvic->r0 = (uint32_t)signo;\n    tramp_nvic->psr = cur_nvic->psr;\n\n    t->tb.sp = (t->tb.osp - (EXTRA_FRAME_SIZE + NVIC_FRAME_SIZE));\n\n    t->tb.sp -= EXTRA_FRAME_SIZE;\n    memcpy((void *)t->tb.sp, (void *)cur_extra, EXTRA_FRAME_SIZE);\n    t->tb.flags |= TASK_FLAG_SIGNALED;\n    task_resume(t);\n}\n\n#else\n#define check_pending_signals(...) do{}while(0)\n#define add_handler(...) (0)\n#define del_handler(...) (0)\n#define sig_hdlr_return NULL\n\nstatic int catch_signal(struct task *t, int signo, sigset_t orig_mask)\n{\n    (void)orig_mask;\n    if (signo != SIGCHLD)\n        task_terminate(t);\n    return 0;\n}\n#endif\n\nvoid task_resume(struct task *t);\nvoid task_resume_lock(struct task *t);\nvoid task_stop(struct task *t);\nvoid task_continue(struct task *t);\n\nint sys_sigaction_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct sigaction *sa = (struct sigaction *)arg2;\n    struct sigaction *sa_old = (struct sigaction *)arg3;\n    struct task_handler *sighdlr;\n\n    if (sa && task_ptr_valid(sa))\n        return -EACCES;\n    if (sa_old && task_ptr_valid(sa_old))\n        return -EACCES;\n\n    if (_cur_task->tb.pid < 1)\n        return -EINVAL;\n\n    if (arg1 >= SIGMAX || arg1 < 1)\n        return -EINVAL;\n\n    /* Populating sa_old */\n    if (sa_old) {\n        sighdlr = _cur_task->tb.sighdlr;\n        while (sighdlr) {\n            if (arg1 == sighdlr->signo)\n                break;\n            sighdlr = sighdlr->next;\n        }\n        if (sighdlr) {\n            sa_old->sa_mask = (sigset_t)sighdlr->mask;\n            sa_old->sa_handler = sighdlr->hdlr;\n        } else {\n            sa_old->sa_mask = (sigset_t)0u;\n            sa_old->sa_handler = SIG_DFL;\n        }\n        sa_old->sa_flags = 0;\n        sa_old->sa_restorer = NULL;\n    }\n    if (sa)\n        add_handler(_cur_task, arg1, sa->sa_handler, sa->sa_mask);\n    return 0;\n}\n\nint sys_sigprocmask_hdlr(int how, const sigset_t *set, sigset_t *oldset)\n{\n    if (set &&\n        ((how != SIG_SETMASK) && (how != SIG_BLOCK) && (how != SIG_UNBLOCK)))\n        return -EINVAL;\n\n    if (!set && !oldset)\n        return -EINVAL;\n\n    if (oldset) {\n        if (task_ptr_valid(oldset))\n            return -EACCES;\n        *oldset = _cur_task->tb.sigmask;\n    }\n\n    if (set) {\n        if (task_ptr_valid(set))\n            return -EACCES;\n        if (how == SIG_SETMASK)\n            _cur_task->tb.sigmask = *set;\n        else if (how == SIG_BLOCK)\n            _cur_task->tb.sigmask |= *set;\n        else\n            _cur_task->tb.sigmask &= ~(*set);\n        check_pending_signals(_cur_task);\n    }\n    return 0;\n}\n\nint sys_sigsuspend_hdlr(const sigset_t *mask)\n{\n    uint32_t orig_mask = _cur_task->tb.sigmask;\n    if (!mask)\n        return -EINVAL;\n    if (task_ptr_valid(mask))\n        return -EACCES;\n\n    _cur_task->tb.sigmask = ~(*mask);\n    task_suspend();\n    _cur_task->tb.sigmask = orig_mask;\n\n    /* Success. */\n    return -EINTR;\n}\n\n/********************************/\n/*           working dir        */\n/********************************/\n/********************************/\n/********************************/\n/**/\n/**/\n/**/\nstruct fnode *task_getcwd(void)\n{\n    return _cur_task->tb.cwd;\n}\nvoid task_chdir(struct fnode *f)\n{\n    _cur_task->tb.cwd = f;\n}\nstatic __inl void *msp_read(void)\n{\n    void *ret = NULL;\n    asm volatile(\"mrs %0, msp\" : \"=r\"(ret));\n    return ret;\n}\n\nstatic __inl void *psp_read(void)\n{\n    void *ret = NULL;\n    asm volatile(\"mrs %0, psp\" : \"=r\"(ret));\n    return ret;\n}\n\nint scheduler_ntasks(void)\n{\n    return number_of_tasks;\n}\nint scheduler_task_state(int pid)\n{\n    struct task *t = tasklist_get(&tasks_running, pid);\n    if (!t)\n        t = tasklist_get(&tasks_idling, pid);\n    if (t)\n        return t->tb.state;\n    else\n        return TASK_OVER;\n}\n\nint scheduler_can_sleep(void)\n{\n    if (tasklist_len(&tasks_running) == 1)\n        return 1;\n    else\n        return 0;\n}\n\nunsigned scheduler_stack_used(int pid)\n{\n    struct task *t = tasklist_get(&tasks_running, pid);\n    if (!t)\n        t = tasklist_get(&tasks_idling, pid);\n    if (t)\n        return SCHEDULER_STACK_SIZE -\n               ((char *)t->tb.sp - (char *)t->tb.cur_stack);\n    else\n        return 0;\n}\n\nchar *scheduler_task_name(int pid)\n{\n    struct task *t = tasklist_get(&tasks_running, pid);\n    if (!t)\n        t = tasklist_get(&tasks_idling, pid);\n    if (t) {\n        char **argv = t->tb.arg;\n        if (argv)\n            return argv[0];\n    } else\n        return NULL;\n}\n\nstatic uint16_t scheduler_get_cur_pid(void)\n{\n    if (!_cur_task)\n        return 0;\n    return _cur_task->tb.pid;\n}\n\nuint16_t this_task_getpid(void)\n{\n    return scheduler_get_cur_pid();\n}\nint task_running(void)\n{\n    return (_cur_task->tb.state == TASK_RUNNING);\n}\nint task_timeslice(void)\n{\n    return (--_cur_task->tb.timeslice);\n}\nvoid task_end(void)\n{\n    /* We have to set the stack pointer because we jumped here\n     * after setting lr to task_end into the NVIC_FRAME and there\n     * we were using the sp of the task's parent */\n    asm volatile(\"msr \" PSP \", %0\" ::\"r\"(_cur_task->tb.sp));\n    /* here we need to be in a irqoff context\n       because we are dealing with the scheduler\n       data structures, otherwise we could produce dead code\n       after callling running_to_idling */\n    irq_off();\n    running_to_idling(_cur_task);\n    _cur_task->tb.state = TASK_ZOMBIE;\n    asm volatile(\"mov %0, r0\" : \"=r\"(_cur_task->tb.exitval));\n    irq_on();\n    while (1) {\n        task_suspend_to(TASK_ZOMBIE);\n    }\n}\n\n/********************************/\n/*         Task creation        */\n/***      vfork() / exec()    ***/\n/********************************/\n/********************************/\n/**/\n/**/\n/**/\n\nstatic void task_resume_vfork(struct task *t);\n\n/* Duplicate exec() args into the new process address space.\n*/\nstatic void *task_pass_args(void *_args)\n{\n    char **args = (char **)_args;\n    char **new = NULL;\n    int i = 0, n = 0;\n    if (!_args)\n        return NULL;\n    while (args[n] != NULL) {\n        n++;\n    }\n    new = u_malloc((n + 1) * (sizeof(char *)));\n\n    if (!new)\n        return NULL;\n\n    new[n] = NULL;\n\n    for (i = 0; i < n; i++) {\n        size_t l = strlen(args[i]);\n        if (l > 0) {\n            new[i] = u_malloc(l + 1);\n            if (!new[i])\n                break;\n            memcpy(new[i], args[i], l + 1);\n        }\n    }\n    return new;\n}\n\nstatic void task_create_real(struct task *new, struct vfs_info *vfsi, void *arg,\n                             unsigned int nice)\n{\n    struct nvic_stack_frame *nvic_frame;\n    struct extra_stack_frame *extra_frame;\n    uint8_t *sp;\n\n    if (nice < NICE_RT)\n        nice = NICE_RT;\n\n    if (nice > NICE_MAX)\n        nice = NICE_MAX;\n\n    new->tb.start = vfsi->init;\n    new->tb.arg = task_pass_args(arg);\n    new->tb.timeslice = TIMESLICE(new);\n    new->tb.state = TASK_RUNNABLE;\n    new->tb.sighdlr = NULL;\n    new->tb.sigpend = 0;\n    new->tb.sigmask = 0;\n    new->tb.tracer = NULL;\n    new->tb.timer_id = -1;\n    new->tb.specifics = NULL;\n    new->tb.n_specifics = 0;\n\n    if ((new->tb.flags &TASK_FLAG_VFORK) != 0) {\n        struct task *pt = tasklist_get(&tasks_idling, new->tb.ppid);\n        if (!pt)\n            pt = tasklist_get(&tasks_running, new->tb.ppid);\n        if (pt) {\n            /* Restore parent's stack */\n            memcpy((void *)pt->tb.cur_stack, (void *)&new->stack,\n                   SCHEDULER_STACK_SIZE);\n            task_resume_vfork(pt);\n        }\n        new->tb.flags &= (~TASK_FLAG_VFORK);\n    }\n\n    /* stack memory */\n    sp = (((uint8_t *)(&new->stack)) + SCHEDULER_STACK_SIZE - NVIC_FRAME_SIZE);\n\n    new->tb.cur_stack = &new->stack;\n\n    /* Change relocated section ownership */\n    fmalloc_chown((void *)vfsi->pic, new->tb.pid);\n\n    /* Stack frame is at the end of the stack space,\n       the NVIC_FRAME is required for context-switching */\n    nvic_frame = (struct nvic_stack_frame *)sp;\n    memset(nvic_frame, 0, NVIC_FRAME_SIZE);\n    nvic_frame->r0 = (uint32_t) new->tb.arg;\n    nvic_frame->pc = (uint32_t) new->tb.start;\n    nvic_frame->lr = (uint32_t)task_end;\n    nvic_frame->psr = 0x01000000u;\n    /* The EXTRA_FRAME is needed in order to save/restore\n       the task context when servicing PendSV exceptions */\n    sp -= EXTRA_FRAME_SIZE;\n    extra_frame = (struct extra_stack_frame *)sp;\n    extra_frame->r9 = new->tb.vfsi->pic;\n    new->tb.sp = (uint32_t *)sp;\n}\n\nint task_create(struct vfs_info *vfsi, void *arg, unsigned int nice)\n{\n    struct task *new;\n    int i;\n    struct filedesc_table *ft;\n\n    new = task_space_alloc(sizeof(struct task));\n    if (!new) {\n        return -ENOMEM;\n    }\n    memset(&new->tb, 0, sizeof(struct task_block));\n    new->tb.pid = next_pid();\n    new->tb.tid = 1;\n    new->tb.tgroup = NULL;\n\n    new->tb.ppid = scheduler_get_cur_pid();\n    new->tb.nice = nice;\n    new->tb.filedesc_table = NULL;\n    new->tb.flags = 0;\n    new->tb.cwd = fno_search(\"/\");\n    new->tb.vfsi = vfsi;\n    new->tb.tracer = NULL;\n\n    ft = _cur_task->tb.filedesc_table;\n\n    /* Inherit cwd, file descriptors from parent */\n    if (new->tb.ppid > 1) { /* Start from parent #2 */\n        new->tb.cwd = task_getcwd();\n        for (i = 0; (ft) && (i < ft->n_files); i++) {\n            task_filedesc_add_to_task(new, ft->fdesc[i].fno);\n            new->tb.filedesc_table->fdesc[i].mask = ft->fdesc[i].mask;\n        }\n    }\n\n    new->tb.next = NULL;\n    tasklist_add(&tasks_running, new);\n\n    number_of_tasks++;\n    task_create_real(new, vfsi, arg, nice);\n    new->tb.state = TASK_RUNNABLE;\n    return new->tb.pid;\n}\n\nint scheduler_exec(struct vfs_info *vfsi, void *args)\n{\n    struct task *t = _cur_task;\n\n    t->tb.vfsi = vfsi;\n    task_create_real(t, vfsi, (void *)args, t->tb.nice);\n    asm volatile(\"msr \" PSP \", %0\" ::\"r\"(_cur_task->tb.sp));\n    t->tb.state = TASK_RUNNING;\n    mpu_task_on((void *)(((uint32_t)t->tb.cur_stack) -\n                         (sizeof(struct task_block) + F_MALLOC_OVERHEAD)));\n    return 0;\n}\n\nint sys_vfork_hdlr(void)\n{\n    struct task *new;\n    int i;\n    uint32_t sp_off =\n        (uint8_t *)_cur_task->tb.sp - (uint8_t *)_cur_task->tb.cur_stack;\n    uint32_t vpid;\n    struct filedesc_table *ft = _cur_task->tb.filedesc_table;\n\n    if (_cur_task->tb.tid != 1) {\n        /* Prohibit vfork() from a thread */\n        return -ENOSYS;\n    }\n\n    new = task_space_alloc(sizeof(struct task));\n    if (!new) {\n        return -ENOMEM;\n    }\n    memset(&new->tb, 0, sizeof(struct task_block));\n    vpid = next_pid();\n    new->tb.pid = vpid;\n    new->tb.tid = 1;\n    new->tb.tgroup = NULL;\n    new->tb.ppid = scheduler_get_cur_pid();\n    new->tb.nice = _cur_task->tb.nice;\n    new->tb.filedesc_table = NULL;\n    new->tb.arg = NULL;\n    new->tb.vfsi = NULL;\n    new->tb.flags = TASK_FLAG_VFORK;\n    new->tb.cwd = task_getcwd();\n    new->tb.timer_id = -1;\n    new->tb.specifics = NULL;\n    new->tb.n_specifics = 0;\n\n    /* Inherit cwd, file descriptors from parent */\n    if (new->tb.ppid > 1) { /* Start from parent #2 */\n        for (i = 0; (ft) && (i < ft->n_files); i++) {\n            task_filedesc_add_to_task(new, ft->fdesc[i].fno);\n            new->tb.filedesc_table->fdesc[i].mask = ft->fdesc[i].mask;\n        }\n        /* Inherit signal mask */\n        new->tb.sigmask = _cur_task->tb.sigmask;\n    }\n\n    new->tb.next = NULL;\n    tasklist_add(&tasks_running, new);\n    number_of_tasks++;\n\n    /* Set parent's vfork retval by writing on stacked r0 */\n    *((uint32_t *)(_cur_task->tb.sp + EXTRA_FRAME_SIZE)) = vpid;\n\n    /* Copy parent's stack in own stack space, but don't use it:\n     * sp remains in the parent's pool.\n     * This will be restored upon exit/exec\n     */\n    memcpy(&new->stack, _cur_task->tb.cur_stack, SCHEDULER_STACK_SIZE);\n    if (new != _cur_task) {\n        new->tb.sp = _cur_task->tb.sp;\n        new->tb.cur_stack = _cur_task->tb.cur_stack;\n        new->tb.state = TASK_RUNNABLE;\n    }\n    /* Vfork: Caller task suspends until child calls exec or exits */\n    asm volatile(\"msr \" PSP \", %0\" ::\"r\"(new->tb.sp));\n    task_suspend_to(TASK_FORKED);\n\n    return vpid;\n}\n/********************************/\n/*         POSIX threads        */\n/********************************/\n/********************************/\n/********************************/\n/**/\n/**/\n/**/\n\n#ifdef CONFIG_PTHREADS\n\nstatic struct task *pthread_get_task(int pid, int tid)\n{\n    struct task *t = NULL;\n    struct task *leader = NULL;\n    struct thread_group *group = NULL;\n    int i;\n\n    leader = tasklist_get(&tasks_running, pid);\n    if (!leader)\n        leader = tasklist_get(&tasks_idling, pid);\n    if (!leader)\n        return NULL;\n\n    if (tid == 1)\n        return leader;\n\n    group = leader->tb.tgroup;\n\n    if (!group || !group->threads || group->n_threads < 2)\n        return NULL;\n\n    for (i = 0; i < group->n_threads; i++) {\n        t = group->threads[i];\n        if (t->tb.tid == tid) {\n            if (t->tb.state == TASK_OVER)\n                return NULL;\n            return t;\n        }\n    }\n    return NULL;\n}\n\nstatic int pthread_add(struct task *cur, struct task *new)\n{\n    int i;\n    struct thread_group *group = cur->tb.tgroup;\n    struct task **old_tgroup;\n\n    if (!group) {\n        group = kcalloc(sizeof(struct thread_group), 1);\n        if (!group)\n            return -ENOMEM;\n        group->threads = kcalloc(sizeof(struct task *), 2);\n        if (!group->threads) {\n            kfree(group);\n            return -ENOMEM;\n        }\n        cur->tb.tgroup = group;\n        new->tb.tgroup = group;\n        group->threads[0] = cur;\n        group->threads[1] = new;\n        group->n_threads = 2;\n        group->max_tid = 2;\n        group->active_threads = 2;\n        return 2;\n    }\n    for (i = 0; i < group->n_threads; i++) {\n        if (group->threads[i] == NULL) {\n            group->threads[i] = new;\n            new->tb.tgroup = group;\n            new->tb.tid = ++group->max_tid;\n            group->active_threads++;\n            return new->tb.tid;\n        }\n    }\n    ++group->n_threads;\n    old_tgroup = group->threads;\n    group->threads =\n        krealloc(group->threads, sizeof(struct task *) * group->n_threads);\n    if (!group->threads) {\n        group->threads = old_tgroup;\n        --group->n_threads;\n        return -ENOMEM;\n    }\n    group->threads[group->n_threads - 1] = new;\n    new->tb.tgroup = group;\n    new->tb.tid = ++group->max_tid;\n    group->active_threads++;\n    return new->tb.tid;\n}\n\nstatic __inl int pthread_destroy_task(struct task *t)\n{\n    struct task *t_joiner;\n\n    running_to_idling(t);\n    if (t->tb.tid > 1 &&\n        (t->tb.flags & TASK_FLAG_DETACHED) == TASK_FLAG_DETACHED) {\n        t->tb.state = TASK_OVER;\n        tasklet_add(task_destroy, t);\n        return TASK_OVER;\n    } else {\n        t->tb.state = TASK_ZOMBIE;\n        if (t->tb.tid > 1 && t->tb.joiner_thread_tid) {\n            t_joiner = pthread_get_task(t->tb.pid, t->tb.joiner_thread_tid);\n            if (t_joiner)\n                task_resume(t_joiner);\n        }\n        return TASK_ZOMBIE;\n    }\n}\n\nstatic void pthread_end(void)\n{\n    /* We have to set the stack pointer because we jumped here\n     * after setting lr to pthread_end into the NVIC_FRAME and there\n     * we were using the sp of the thread's parent */\n    asm volatile(\"msr \" PSP \", %0\" ::\"r\"(_cur_task->tb.sp));\n    int thread_state;\n    /* storing thread return value */\n    asm volatile(\"mov %0, r0\" : \"=r\"(_cur_task->tb.exitval));\n    irq_off();\n    thread_state = pthread_destroy_task(_cur_task);\n    _cur_task->tb.tgroup->active_threads--;\n    irq_on();\n    while (1) {\n        task_suspend_to(thread_state);\n    }\n}\n\n/* Finalize thread creation, code shared by pthreads/kthreads. */\nstatic inline void thread_create(struct task *new,\n                                 void (*start_routine)(void *), void *arg)\n{\n    struct nvic_stack_frame *nvic_frame;\n    struct extra_stack_frame *extra_frame;\n    uint8_t *sp;\n    new->tb.joiner_thread_tid = 0;\n    new->tb.start = start_routine;\n    new->tb.arg = arg;\n    new->tb.next = NULL;\n    tasklist_add(&tasks_running, new);\n    number_of_tasks++;\n    new->tb.timeslice = TIMESLICE(new);\n    new->tb.state = TASK_RUNNABLE;\n    sp = (((uint8_t *)(&new->stack)) + SCHEDULER_STACK_SIZE - NVIC_FRAME_SIZE);\n    new->tb.cur_stack = &new->stack;\n\n    /* Stack frame is at the end of the stack space */\n    nvic_frame = (struct nvic_stack_frame *)sp;\n    memset(nvic_frame, 0, NVIC_FRAME_SIZE);\n    nvic_frame->r0 = (uint32_t) new->tb.arg;\n    nvic_frame->pc = (uint32_t) new->tb.start;\n    nvic_frame->lr = (uint32_t)pthread_end;\n    nvic_frame->psr = 0x01000000u;\n    sp -= EXTRA_FRAME_SIZE;\n    extra_frame = (struct extra_stack_frame *)sp;\n    extra_frame->r9 = new->tb.vfsi->pic;\n    new->tb.sp = (uint32_t *)sp;\n}\n\n/* Pthread create handler. Call be like:\n * int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void\n * *(*start_routine) (void *), void *arg)\n */\nint sys_pthread_create_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3,\n                            uint32_t arg4, uint32_t arg5)\n{\n    pthread_t *thread = (pthread_t *)arg1;\n    pthread_attr_t *attr = (pthread_attr_t *)arg2;\n    void (*start_routine)(void *) = (void (*)(void *))arg3;\n    void *arg = (void *)arg4;\n    (void)arg5;\n    struct task *new;\n    int i;\n    struct filedesc_table *ft = _cur_task->tb.filedesc_table;\n\n    if (!thread || (task_ptr_valid(thread) < 0) || (task_ptr_valid(attr) < 0))\n        return -EINVAL;\n\n    new = task_space_alloc(sizeof(struct task));\n    if (!new) {\n        return -ENOMEM;\n    }\n    memset(&new->tb, 0, sizeof(struct task_block));\n\n    new->tb.tid = pthread_add(_cur_task, new);\n    if (new->tb.tid < 0) {\n        task_space_free(new);\n        return -ENOMEM;\n    }\n    if (attr && *attr == PTHREAD_CREATE_DETACHED)\n        new->tb.flags = TASK_FLAG_DETACHED | TASK_FLAG_CANCELABLE;\n    else\n        new->tb.flags = TASK_FLAG_CANCELABLE;\n\n    new->tb.pid = _cur_task->tb.pid;\n    new->tb.ppid = _cur_task->tb.ppid;\n    new->tb.nice = _cur_task->tb.nice;\n    new->tb.filedesc_table = _cur_task->tb.filedesc_table;\n    new->tb.vfsi = _cur_task->tb.vfsi;\n    new->tb.cwd = task_getcwd();\n    new->tb.sigmask = _cur_task->tb.sigmask;\n    new->tb.sighdlr = _cur_task->tb.sighdlr;\n    new->tb.tracer = NULL;\n    new->tb.timer_id = -1;\n    new->tb.n_specifics = _cur_task->tb.n_specifics;\n    if (new->tb.n_specifics > 0) {\n        new->tb.specifics = kalloc(new->tb.n_specifics * (sizeof(pthread_key_t)));\n        if (new->tb.specifics) {\n            memcpy(new->tb.specifics, _cur_task->tb.specifics, new->tb.n_specifics * (sizeof(pthread_key_t)));\n        } else {\n            new->tb.n_specifics = 0;\n        }\n    }\n    thread_create(new, start_routine, arg);\n    *thread = ((new->tb.pid << 16) | (new->tb.tid & 0xFFFF));\n    return 0;\n}\n\nint sys_pthread_kill_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3,\n                     uint32_t arg4, uint32_t arg5)\n{\n\n    pthread_t thread = (pthread_t )arg1;\n    int sig = (int)arg2;\n    struct task *t;\n    if (!thread)\n        return -EINVAL;\n    t = pthread_get_task((thread & 0xFFFF0000) >> 16, (thread & 0xFFFF));\n    if (!t)\n        return -ESRCH;\n    pthread_destroy_task(t);\n\n    while(t == this_task()) {\n        task_preempt();\n    }\n}\n\nstruct task *kthread_create(void(routine)(void *), void *arg)\n{\n    struct task *new = task_space_alloc(sizeof(struct task));\n    void (*start_routine)(void *) = (void (*)(void *))routine;\n    if (!new) {\n        return NULL;\n    }\n    irq_off();\n    memset(&new->tb, 0, sizeof(struct task_block));\n    new->tb.tid = pthread_add(kernel, new);\n    if (new->tb.tid < 0) {\n        task_space_free(new);\n        return NULL;\n    }\n    new->tb.flags = TASK_FLAG_DETACHED | TASK_FLAG_CANCELABLE;\n    new->tb.pid = 0;\n    new->tb.ppid = 0;\n    new->tb.nice = NICE_DEFAULT;\n    new->tb.filedesc_table = NULL;\n    new->tb.vfsi = NULL;\n    new->tb.cwd = NULL;\n    thread_create(new, start_routine, arg);\n    irq_on();\n    return new;\n}\n\nint kthread_cancel(struct task *t)\n{\n    if (!t || (t->tb.pid != 0) || (t->tb.tid <= 1))\n        return -1;\n    irq_off();\n    if (tasklist_del(&tasks_running, t) == 0)\n        tasklist_add(&tasks_idling, t);\n    t->tb.state = TASK_OVER;\n    tasklet_add(task_destroy, t);\n    irq_on();\n    return 0;\n}\n\nint sys_pthread_exit_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    _cur_task->tb.exitval = arg1;\n    pthread_destroy_task(_cur_task);\n    /* deliver SIGCHLD if this is the last thread */\n    if (_cur_task->tb.tgroup->active_threads == 1)\n        tasklet_add(task_deliver_sigchld, ((void *)(int)_cur_task->tb.ppid));\n    else\n        _cur_task->tb.tgroup->active_threads--;\n}\n\nint sys_pthread_join_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    pthread_t thread = (pthread_t)arg1;\n    void **retval = (void **)arg2;\n    struct task *to_join;\n\n    if (task_ptr_valid((void *)retval) < 0)\n        return -EINVAL;\n    to_join = pthread_get_task((thread & 0xFFFF0000) >> 16, (thread & 0xFFFF));\n    if (!to_join)\n        return -ESRCH;\n    if ((to_join->tb.flags & TASK_FLAG_DETACHED) == TASK_FLAG_DETACHED)\n        return -EINVAL;\n    if (to_join == _cur_task ||\n        _cur_task->tb.joiner_thread_tid == to_join->tb.tid)\n        return -EDEADLK;\n    if (to_join->tb.joiner_thread_tid &&\n        to_join->tb.joiner_thread_tid != _cur_task->tb.tid) {\n        return -EINVAL;\n    }\n    to_join->tb.joiner_thread_tid = _cur_task->tb.tid;\n    if (to_join->tb.state != TASK_ZOMBIE) {\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n    if (retval)\n        *retval = (void *)to_join->tb.exitval;\n    to_join->tb.state = TASK_OVER;\n    tasklet_add(task_destroy, to_join);\n    return 0;\n}\n\nint sys_pthread_detach_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    pthread_t thread = (pthread_t)arg1;\n\n    struct task *t =\n        pthread_get_task((thread & 0xFFFF0000) >> 16, (thread & 0xFFFF));\n    if (!t)\n        return -ESRCH;\n    t->tb.flags |= TASK_FLAG_DETACHED;\n    return 0;\n}\n\nint sys_pthread_setcancelstate_hdlr(int arg1, int arg2, int arg3, int arg4,\n                                    int arg5)\n{\n    int state = arg1;\n    int *oldstate = (int *)arg2;\n    struct task *t_joiner;\n\n    if (task_ptr_valid((void *)oldstate) < 0)\n        return -EINVAL;\n    if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)\n        return -EINVAL;\n    if (oldstate) {\n        if ((_cur_task->tb.flags & TASK_FLAG_CANCELABLE) ==\n            TASK_FLAG_CANCELABLE)\n            *oldstate = PTHREAD_CANCEL_ENABLE;\n        else\n            *oldstate = PTHREAD_CANCEL_DISABLE;\n    }\n    if (state == PTHREAD_CANCEL_ENABLE) {\n        _cur_task->tb.flags |= TASK_FLAG_CANCELABLE;\n        if ((_cur_task->tb.flags & TASK_FLAG_PENDING_CANC) ==\n            TASK_FLAG_PENDING_CANC) {\n            running_to_idling(_cur_task);\n            if ((_cur_task->tb.flags & TASK_FLAG_DETACHED) ==\n                TASK_FLAG_DETACHED) {\n                _cur_task->tb.state = TASK_OVER;\n                tasklet_add(task_destroy, _cur_task);\n            } else {\n                _cur_task->tb.state = TASK_ZOMBIE;\n                _cur_task->tb.exitval = PTHREAD_CANCELED;\n                if (_cur_task->tb.joiner_thread_tid) {\n                    t_joiner = pthread_get_task(\n                        _cur_task->tb.pid, _cur_task->tb.joiner_thread_tid);\n                    if (t_joiner)\n                        task_resume(t_joiner);\n                }\n            }\n        }\n    } else\n        _cur_task->tb.flags &= ~TASK_FLAG_CANCELABLE;\n    return 0;\n}\n\nint sys_pthread_cancel_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    pthread_t thread = (pthread_t)arg1;\n    struct task *t =\n        pthread_get_task((thread & 0xFFFF0000) >> 16, (thread & 0xFFFF));\n    struct task *t_joiner;\n\n    if (t) {\n        if ((t->tb.flags & TASK_FLAG_CANCELABLE) == TASK_FLAG_CANCELABLE) {\n            running_to_idling(t);\n            if ((t->tb.flags & TASK_FLAG_DETACHED) == TASK_FLAG_DETACHED) {\n                t->tb.state = TASK_OVER;\n                tasklet_add(task_destroy, t);\n            } else {\n                t->tb.state = TASK_ZOMBIE;\n                t->tb.exitval = PTHREAD_CANCELED;\n                if (t->tb.joiner_thread_tid) {\n                    t_joiner =\n                        pthread_get_task(t->tb.pid, t->tb.joiner_thread_tid);\n                    if (t_joiner)\n                        task_resume(t_joiner);\n                }\n            }\n        } else {\n            t->tb.flags |= TASK_FLAG_PENDING_CANC;\n        }\n        return 0;\n    }\n    return -ESRCH;\n}\n\nint sys_pthread_self_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    pthread_t thread;\n    thread = (_cur_task->tb.pid << 16) | (_cur_task->tb.tid & 0xFFFF);\n    return (int)thread;\n}\n\nint sys_pthread_mutex_init_hdlr(int arg1, int arg2, int arg3, int arg4,\n                                int arg5)\n{\n    mutex_t **mutex = (mutex_t **)arg1;\n    if (!mutex || (task_ptr_valid((void *)mutex) < 0))\n        return -EPERM;\n    else\n        *mutex = mutex_init();\n    if (!(*mutex))\n        return -ENOMEM;\n    return 0;\n}\n\nint sys_pthread_mutex_destroy_hdlr(int arg1, int arg2, int arg3, int arg4,\n                                   int arg5)\n{\n    mutex_t *mutex = (mutex_t *)arg1;\n    if (mutex)\n        mutex_destroy(mutex);\n    else\n        return -EINVAL;\n    return 0;\n}\n\nint sys_pthread_mutex_lock_hdlr(int arg1, int arg2, int arg3, int arg4,\n                                int arg5)\n{\n    mutex_t **mutex = (mutex_t **)arg1;\n    if (!mutex)\n        return -EINVAL;\n    /* the mutex has to be initialized first if it's NULL*/\n    if (!(*mutex)) {\n        *mutex = mutex_init();\n        if (!(*mutex))\n            return -EAGAIN;\n    }\n    return mutex_lock(*mutex);\n}\n\nint sys_pthread_mutex_trylock_hdlr(int arg1, int arg2, int arg3, int arg4,\n                                   int arg5)\n{\n    mutex_t **mutex = (mutex_t **)arg1;\n    if (!mutex)\n        return -EINVAL;\n    /* the mutex has to be initialized first if it's NULL*/\n    if (!(*mutex)) {\n        *mutex = mutex_init();\n        if (!(*mutex))\n            return -EAGAIN;\n    }\n    return mutex_trylock(*mutex);\n}\n\nint sys_pthread_mutex_unlock_hdlr(int arg1, int arg2, int arg3, int arg4,\n                                  int arg5)\n{\n    mutex_t *mutex = (mutex_t *)arg1;\n    if (!mutex)\n        return -EINVAL;\n    return mutex_unlock(mutex);\n}\n\n\nint sys_pthread_key_create_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct task *t = this_task();\n    void *newarray = krealloc(t->tb.specifics, sizeof(pthread_key_t) * (t->tb.n_specifics + 1));\n    pthread_key_t *key = (pthread_key_t *)arg1;\n    if (newarray) {\n        t->tb.specifics = newarray;\n        *key = t->tb.n_specifics;\n        t->tb.n_specifics++;\n    }\n    return 0;\n}\n\nint sys_pthread_setspecific_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct task *t = this_task();\n    pthread_key_t key = (pthread_key_t)arg1;\n    if (key < 0 || key >= t->tb.n_specifics)\n        return -EINVAL;\n    t->tb.specifics[key] = (uint32_t)arg2;\n    return 0;\n}\n\nint sys_pthread_getspecific_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    struct task *t = this_task();\n    pthread_key_t key = (pthread_key_t)arg1;\n    if (key < 0 || key >= t->tb.n_specifics)\n        return -EINVAL;\n    (*(uint32_t*)arg2) = t->tb.specifics[key];\n    return 0;\n}\n#else /* if !CONFIG_PTHREADS */\nint sys_pthread_create_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\n\nint sys_pthread_exit_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\n\n\nint sys_pthread_join_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_detach_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_cancel_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_self_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_setcancelstate_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_mutex_init_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_mutex_destroy_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_mutex_lock_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_mutex_trylock_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_mutex_unlock_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_kill_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_key_create_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_setspecific_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\nint sys_pthread_getspecific_hdlr(int arg1, int arg2, int arg3, int arg4, int arg5)\n{\n    return -EOPNOTSUPP;\n}\n\n#endif /* CONFIG_PTHREADS */\n\n\n/********************************/\n/*         Task switching       */\n/********************************/\n/********************************/\n/********************************/\n/**/\n/**/\n/**/\n/* In order to keep the code efficient, the stack layout of armv6 and armv7 do NOT match! */\nstatic __naked void save_kernel_context(void)\n{\n    asm volatile(\"mrs r0, \" MSP \"           \");\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    asm volatile(\"stmdb r0!, {r4-r11}   \");\n#elif defined(__ARM_ARCH_6M__)\n    asm volatile(\"sub   r0,#0x10\");\n    asm volatile(\"stm   r0!,{r4-R7}\"); // Save r4-r7\n    asm volatile(\"mov   r4,r8\");\n    asm volatile(\"mov   r5,r9\");\n    asm volatile(\"mov   r6,r10\");\n    asm volatile(\"mov   r7,r11\");\n    asm volatile(\"sub   r0,#0x20\");\n    asm volatile(\"stm   r0!,{r4-R7}\"); // Save r8-r11\n    asm volatile(\"sub   r0,#0x10\");\n#endif\n    asm volatile(\"msr \" MSP \", r0           \");\n    asm volatile(\"isb\");\n    asm volatile(\"bx lr                 \");\n}\n\nstatic __naked void save_task_context(void)\n{\n    asm volatile(\"mrs r0, \" PSP \"           \");\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    asm volatile(\"stmdb r0!, {r4-r11}   \");\n#elif defined(__ARM_ARCH_6M__)\n    asm volatile(\"sub   r0,#0x10\");\n    asm volatile(\"stm   r0!,{r4-R7}\"); // Save r4-r7\n    asm volatile(\"mov   r4,r8\");\n    asm volatile(\"mov   r5,r9\");\n    asm volatile(\"mov   r6,r10\");\n    asm volatile(\"mov   r7,r11\");\n    asm volatile(\"sub   r0,#0x20\");\n    asm volatile(\"stm   r0!,{r4-R7}\"); // Save r8-r11\n    asm volatile(\"sub   r0,#0x10\");\n#endif\n    asm volatile(\"msr \" PSP \", r0           \");\n    asm volatile(\"isb\");\n    asm volatile(\"bx lr                 \");\n}\n\nstatic uint32_t runnable = RUN_HANDLER;\n\nstatic __naked void restore_kernel_context(void)\n{\n    asm volatile(\"mrs r0, \" MSP \"          \");\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    asm volatile(\"ldmfd r0!, {r4-r11}  \");\n#elif defined(__ARM_ARCH_6M__)\n    asm volatile(\"ldm r0!,{r4-r7}\");\n    asm volatile(\"mov r8,r4\");\n    asm volatile(\"mov r9,r5\");\n    asm volatile(\"mov r10,r6\");\n    asm volatile(\"mov r11,r7\");\n    asm volatile(\"ldm r0!,{r4-r7}\");\n#endif\n    asm volatile(\"msr \" MSP \", r0\");\n    asm volatile(\"isb\");\n    asm volatile(\"bx lr                 \");\n}\n\nstatic __naked void restore_task_context(void)\n{\n    asm volatile(\"mrs r0, \" PSP \"          \");\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    asm volatile(\"ldmfd r0!, {r4-r11}  \");\n#elif defined(__ARM_ARCH_6M__)\n    asm volatile(\"ldm r0!,{r4-r7}\");\n    asm volatile(\"mov r8,r4\");\n    asm volatile(\"mov r9,r5\");\n    asm volatile(\"mov r10,r6\");\n    asm volatile(\"mov r11,r7\");\n    asm volatile(\"ldm r0!,{r4-r7}\");\n#endif\n    asm volatile(\"msr \" PSP \", r0          \");\n    asm volatile(\"isb\");\n    asm volatile(\"bx lr                 \");\n}\n\nstatic __inl void task_switch(void)\n{\n    int i;\n    struct task *t;\n    if (forced_task) {\n        _cur_task = forced_task;\n        forced_task = NULL;\n        return;\n    }\n    t = _cur_task;\n    /* Checks that the _cur_task hasn't left the \"task_running\" list.\n     * If it's not in the valid state, revert task-switching to the head of\n     * task_running */\n    if (((t->tb.state != TASK_RUNNING) && (t->tb.state != TASK_RUNNABLE)) ||\n        (t->tb.next == NULL))\n        t = tasks_running;\n    else\n        t = t->tb.next;\n    t->tb.timeslice = TIMESLICE(t);\n    t->tb.state = TASK_RUNNING;\n    _cur_task = t;\n}\n\n#pragma GCC push_options\n#pragma GCC optimize (\"O0\")\n\n/* C ABI cannot mess with the stack, we will */\nvoid __naked pend_sv_handler(void)\n{\n    asm volatile(\"cpsid i\");\n    /* save current context on current stack */\n    if (in_kernel()) {\n        save_kernel_context();\n        asm volatile(\"mrs %0, \" MSP \"\" : \"=r\"(_top_stack));\n    } else {\n        save_task_context();\n        asm volatile(\"mrs %0, \" PSP \"\" : \"=r\"(_top_stack));\n    }\n    asm volatile(\"isb\");\n\n    /* save current SP to TCB */\n    _cur_task->tb.sp = _top_stack;\n    if (_cur_task->tb.state == TASK_RUNNING)\n        _cur_task->tb.state = TASK_RUNNABLE;\n\n    /* choose next task */\n    //    if ((_cur_task->tb.flags & TASK_FLAG_SIGNALED) == 0)\n    task_switch();\n\n    /* if switching to a signaled task, adjust sp */\n    //    if ((_cur_task->tb.flags & (TASK_FLAG_IN_SYSCALL |\n    //    TASK_FLAG_SIGNALED)) == ((TASK_FLAG_SIGNALED))) {\n    //        _cur_task->tb.sp += 32;\n    //    }\n\n    if (((int)(_cur_task->tb.sp) - (int)(&_cur_task->stack)) <\n        STACK_THRESHOLD) {\n        kprintf(\"PendSV: Process %d is running out of stack space!\\n\",\n                _cur_task->tb.pid);\n    }\n\n    /* write new stack pointer and restore context */\n    if (in_kernel()) {\n        asm volatile(\"msr \" MSP \", %0\" ::\"r\"(_cur_task->tb.sp));\n        asm volatile(\"isb\");\n        restore_kernel_context();\n        runnable = RUN_KERNEL;\n    } else {\n        mpu_task_on((void *)(((uint32_t)_cur_task->tb.cur_stack) -\n                             (sizeof(struct task_block) + F_MALLOC_OVERHEAD)));\n        asm volatile(\"msr \" PSP \", %0\" ::\"r\"(_cur_task->tb.sp));\n        asm volatile(\"isb\");\n        restore_task_context();\n        runnable = RUN_USER;\n    }\n\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    /* Set control bit for non-kernel threads */\n    if (_cur_task->tb.pid != 0) {\n        asm volatile(\"msr CONTROL, %0\" ::\"r\"(0x01));\n    } else {\n        asm volatile(\"msr CONTROL, %0\" ::\"r\"(0x00));\n    }\n    asm volatile(\"isb\");\n#endif\n\n    /* Set return value selected by the restore procedure;\n       RUN_KERNEL/RUN_USER are special values which inform\n       the CPU we are returning from an exception handler,\n       after detecting such a value the processor pops the\n       correct stack frame (NVIC_FRAME) and jumps to the\n       program counter stored into it, thus resuming task\n       execution.  */\n    asm volatile(\"mov lr, %0\" ::\"r\"(runnable));\n\n    asm volatile(\"cpsie i\");\n    /* return (function is naked) */\n    asm volatile(\"bx lr          \\n\");\n}\n#pragma GCC pop_options\n\n\nvoid kernel_task_init(void)\n{\n    /* task0 = kernel */\n    irq_off();\n    kernel->tb.sp = msp_read(); // SP needs to be current SP\n    kernel->tb.pid = next_pid();\n    kernel->tb.tid = 1;\n    kernel->tb.tgroup = NULL;\n    kernel->tb.ppid = scheduler_get_cur_pid();\n    kernel->tb.nice = NICE_DEFAULT;\n    kernel->tb.start = NULL;\n    kernel->tb.arg = NULL;\n    kernel->tb.timer_id = -1;\n    kernel->tb.filedesc_table = NULL;\n    kernel->tb.timeslice = TIMESLICE(kernel);\n    kernel->tb.state = TASK_RUNNABLE;\n    kernel->tb.cwd = fno_search(\"/\");\n    kernel->tb.state = TASK_RUNNABLE;\n    kernel->tb.next = NULL;\n    tasklist_add(&tasks_running, kernel);\n    irq_on();\n\n    /* Set kernel as current task */\n    _cur_task = kernel;\n}\n\nstatic void task_suspend_to(int newstate)\n{\n    /* Refuse to suspend on main kernel thread. */\n    if ((_cur_task->tb.pid < 1) && (_cur_task->tb.tid < 2))\n        return;\n    running_to_idling(_cur_task);\n    if (_cur_task->tb.state == TASK_RUNNABLE ||\n        _cur_task->tb.state == TASK_RUNNING) {\n        _cur_task->tb.timeslice = 0;\n    }\n    _cur_task->tb.state = newstate;\n    schedule();\n}\n\nvoid task_suspend(void)\n{\n    return task_suspend_to(TASK_WAITING);\n}\n\nvoid task_stop(struct task *t)\n{\n    if (!t)\n        return;\n    if (t->tb.state == TASK_RUNNABLE || t->tb.state == TASK_RUNNING) {\n        t->tb.timeslice = 0;\n    }\n    t->tb.state = TASK_STOPPED;\n    running_to_idling(t);\n    schedule();\n}\n\nvoid task_hit_breakpoint(struct task *t)\n{\n    if (t->tb.tracer) {\n        task_stop(t);\n        task_resume(t->tb.tracer);\n    }\n}\n\nvoid task_preempt(void)\n{\n    _cur_task->tb.timeslice = 0;\n    schedule();\n}\n\nvoid task_preempt_all(void)\n{\n    struct task *t = tasks_running;\n    while (t) {\n        if (t->tb.pid != 0)\n            t->tb.timeslice = 0;\n        t = t->tb.next;\n    }\n    schedule();\n}\n\n\nstatic void task_resume_real(struct task *t, int lock)\n{\n    if (!t)\n        return;\n    if (t->tb.state == TASK_WAITING) {\n        idling_to_running(t);\n        t->tb.state = TASK_RUNNABLE;\n    }\n    if (!lock && (t->tb.nice == NICE_RT)) {\n        forced_task = t;\n        task_preempt_all();\n    }\n}\n\nvoid task_resume_lock(struct task *t)\n{\n    task_resume_real(t, 1);\n}\n\nvoid task_resume(struct task *t)\n{\n    task_resume_real(t, 0);\n}\n\nvoid task_wakeup(struct task *t)\n{\n    task_preempt_all();\n    t->tb.timeslice = TIMESLICE(t);\n    task_resume(t);\n}\n\nvoid task_continue(struct task *t)\n{\n    if ((t) && (t->tb.state == TASK_STOPPED)) {\n        idling_to_running(t);\n        t->tb.state = TASK_RUNNABLE;\n    }\n}\n\nstatic void task_resume_vfork(struct task *t)\n{\n    if ((t) && t->tb.state == TASK_FORKED) {\n        idling_to_running(t);\n        t->tb.state = TASK_RUNNABLE;\n    }\n}\n\nvoid task_deliver_sigchld(void *arg)\n{\n    struct task *t = (struct task *)arg;\n    if (t)\n    task_kill(t->tb.pid, SIGCHLD);\n}\n\nvoid task_deliver_sigtrap(void *arg)\n{\n    struct task *t = (struct task *)arg;\n    if (t)\n        task_kill(t->tb.pid, SIGTRAP);\n}\n\n\nstatic void destroy_thread_group(struct thread_group *group, uint16_t tid)\n{\n#ifdef CONFIG_PTHREADS\n    int i;\n    /* Destroy the entire thread family */\n    for (i = 0; i < group->n_threads; i++) {\n        if (group->threads[i] != NULL) {\n            struct task *th = group->threads[i];\n            if (th->tb.tid != tid) {\n                running_to_idling(th);\n                th->tb.state = TASK_OVER;\n                kfree(th->tb.tgroup->threads);\n                kfree(th->tb.tgroup);\n                th->tb.tgroup = NULL;\n                tasklet_add(task_destroy, th);\n            }\n        }\n    }\n#endif\n}\n\n\n\nvoid task_terminate(struct task *t)\n{\n    int i;\n    if (t) {\n        running_to_idling(t);\n        t->tb.state = TASK_ZOMBIE;\n        t->tb.timeslice = 0;\n\n        if (t->tb.ppid > 0) {\n            struct task *pt = tasklist_get(&tasks_idling, t->tb.ppid);\n            if (!pt)\n                pt = tasklist_get(&tasks_running, t->tb.ppid);\n            if (t->tb.flags & TASK_FLAG_VFORK) {\n                /* Restore parent's stack */\n                if (pt) {\n                    memcpy((void *)pt->tb.cur_stack, (void *)&_cur_task->stack,\n                           SCHEDULER_STACK_SIZE);\n                    t->tb.flags &= ~TASK_FLAG_VFORK;\n                }\n                task_resume_vfork(t);\n            }\n            if (!pt || (pt->tb.state == TASK_ZOMBIE) || (pt->tb.state == TASK_OVER)) {\n                /* Parent task is not there anymore. Init tries to adopt orphan child. */\n                t->tb.ppid = 1;\n                pt = tasklist_get(&tasks_running, 1);\n                if (!pt)\n                    pt = tasklist_get(&tasks_idling, 1);\n            }\n            if (pt)\n                tasklet_add(task_deliver_sigchld, pt);\n\n            task_preempt();\n        }\n    }\n}\n\nint scheduler_get_nice(int pid)\n{\n    struct task *t;\n    t = tasklist_get(&tasks_running, pid);\n    if (!t)\n        t = tasklist_get(&tasks_idling, pid);\n\n    if (!t)\n        return 0;\n    return (int)t->tb.nice;\n}\n\nint sys_getpid_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                    uint32_t arg5)\n{\n    if (!_cur_task)\n        return 0;\n    return _cur_task->tb.pid;\n}\n\nint sys_getppid_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                     uint32_t arg5)\n{\n    if (!_cur_task)\n        return 0;\n    return _cur_task->tb.ppid;\n}\n\nvoid sleepy_task_wakeup(uint32_t now, void *arg)\n{\n    struct task *t = (struct task *)arg;\n    t->tb.timer_id = -1;\n    t->tb.flags |= TASK_FLAG_TIMEOUT;\n    if (t->tb.state == TASK_WAITING)\n        task_resume(t);\n}\n\nint sys_sleep_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                   uint32_t arg5)\n{\n    uint32_t timeout = jiffies + arg1;\n    if (arg1 < 0)\n        return -EINVAL;\n\n    if ((_cur_task->tb.flags & TASK_FLAG_TIMEOUT) != 0) {\n        _cur_task->tb.flags &= (~TASK_FLAG_TIMEOUT);\n        if (_cur_task->tb.timer_id >= 0) {\n            ktimer_del(_cur_task->tb.timer_id);\n            _cur_task->tb.timer_id = -1;\n        }\n        return 0;\n    }\n    _cur_task->tb.timer_id = ktimer_add(arg1, sleepy_task_wakeup, this_task());\n    task_suspend();\n    return SYS_CALL_AGAIN;\n}\n\nvoid kthread_sleep_ms(uint32_t ms)\n{\n    unsigned dl = jiffies + ms;\n    while(dl > jiffies) {\n        kthread_yield();\n    }\n}\n\nvoid alarm_task(uint32_t now, void *arg)\n{\n    struct task *t = (struct task *)arg;\n    if (t) {\n        t->tb.timer_id = -1;\n        task_kill(t->tb.pid, SIGALRM);\n    }\n}\n\nint sys_alarm_hdlr(uint32_t arg1)\n{\n    if (arg1 < 0)\n        return -EINVAL;\n\n    int ret = 0;\n    if (_cur_task->tb.timer_id >= 0) {\n        ktimer_del(_cur_task->tb.timer_id);\n        ret = 1;\n    }\n\n    _cur_task->tb.timer_id = ktimer_add((arg1 * 1000), alarm_task, this_task());\n    return ret;\n}\n\nint sys_ualarm_hdlr(uint32_t arg1, uint32_t arg2)\n{\n    if (arg1 < 0)\n        return -EINVAL;\n\n    int ret = 0;\n    if (_cur_task->tb.timer_id >= 0) {\n        ktimer_del(_cur_task->tb.timer_id);\n        ret = 1;\n    }\n\n    _cur_task->tb.timer_id = ktimer_add(((arg1 / 1000) + 1), alarm_task, this_task());\n    return ret;\n}\n\nvoid task_yield(void)\n{\n    _cur_task->tb.timeslice = 0;\n    schedule();\n}\n\nvoid __naked kthread_yield(void)\n{\n    struct task *t = _cur_task;\n    if (!t || (t->tb.pid != 0) || (t->tb.tid < 2))\n        return;\n    _cur_task->tb.timeslice = 0;\n    schedule();\n    /* return (function is naked) */\n    asm volatile(\"bx lr\");\n}\n\nint sys_sched_yield_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3,\n                         uint32_t arg4, uint32_t arg5)\n{\n    task_yield();\n    return 0;\n};\n\nint sys_poll_hdlr(uint32_t arg1, uint32_t arg2, int arg3)\n{\n    struct pollfd *pfd = (struct pollfd *)arg1;\n    int i, n = (int)arg2;\n    uint32_t timeout;\n    int endless = 0;\n    int ret = 0;\n    struct fnode *f;\n    if (task_ptr_valid((void *)arg1))\n        return -EACCES;\n\n    if (arg3 < 0) {\n        endless = 1;\n    }\n\n    if ((_cur_task->tb.flags & TASK_FLAG_TIMEOUT) != 0) {\n        _cur_task->tb.flags &= (~TASK_FLAG_TIMEOUT);\n        return 0;\n    }\n\n    if ((_cur_task->tb.flags & TASK_FLAG_TIMEOUT) == 0)\n        timeout = jiffies + arg3;\n    else\n        timeout = jiffies;\n\n    while (endless || (jiffies <= timeout)) {\n        for (i = 0; i < n; i++) {\n            f = task_filedesc_get(pfd[i].fd);\n            if (!f || !f->owner || !f->owner->ops.poll) {\n                return -EOPNOTSUPP;\n            }\n            pfd[i].revents = 0;\n            ret += f->owner->ops.poll(f, pfd[i].events, &pfd[i].revents);\n        }\n        if (ret > 0) {\n            if (this_task()->tb.timer_id >= 0) {\n                ktimer_del(this_task()->tb.timer_id);\n                this_task()->tb.timer_id = -1;\n            }\n            _cur_task->tb.flags &= (~TASK_FLAG_TIMEOUT);\n            return ret;\n        }\n\n        if (!endless && (this_task()->tb.timer_id < 0)) {\n            this_task()->tb.timer_id =\n                ktimer_add(timeout - jiffies, sleepy_task_wakeup, this_task());\n        }\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n    if (_cur_task->tb.timer_id >= 0) {\n        ktimer_del(_cur_task->tb.timer_id);\n        _cur_task->tb.timer_id = -1;\n    }\n    return 0;\n}\n\nint sys_waitpid_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3)\n{\n    int *status = (int *)arg2;\n    struct task *t = NULL;\n    int pid = (int)arg1;\n    int options = (int)arg3;\n    if (status && task_ptr_valid(status))\n        return -EACCES;\n    if (pid == 0)\n        return -EINVAL;\n\n    if (pid < -1)\n        return -ENOSYS;\n\n    if (pid != -1) {\n        t = tasklist_get(&tasks_running, pid);\n        /* Check if pid is running, but it's not a child */\n        if (t) {\n            if (t->tb.ppid != _cur_task->tb.ppid)\n                return -ESRCH;\n            else {\n                if ((options & WNOHANG) != 0)\n                    return 0;\n                task_suspend();\n                return SYS_CALL_AGAIN;\n            }\n        }\n\n        t = tasklist_get(&tasks_idling, pid);\n        if (!t || (t->tb.ppid != _cur_task->tb.pid))\n            return -ESRCH;\n        if (t->tb.state == TASK_ZOMBIE)\n            goto child_found;\n        if (t->tb.state == TASK_STOPPED)\n        {\n            /* TODO: set status */\n            return pid;\n        }\n        if (options & WNOHANG)\n            return 0;\n        task_suspend();\n        return SYS_CALL_AGAIN;\n    }\n\n    /* wait for all (pid = -1) */\n    t = tasks_idling;\n    while (t) {\n\n        if ((t->tb.state == TASK_STOPPED) && (t->tb.ppid == _cur_task->tb.pid))\n        {\n            /* TODO: set status */\n            return pid;\n        }\n        if ((t->tb.state == TASK_ZOMBIE) && (t->tb.ppid == _cur_task->tb.pid))\n            goto child_found;\n        t = t->tb.next;\n    }\n    if (options & WNOHANG)\n        return 0;\n    task_suspend();\n    return SYS_CALL_AGAIN;\n\nchild_found:\n    if (arg2) {\n        *((int *)arg2) = t->tb.exitval;\n    }\n    pid = t->tb.pid;\n    /* if this is a thread this is the last active one because it sent a SIGCHLD\n     */\n#ifdef CONFIG_PTHREADS\n    if (t->tb.tgroup)\n        t->tb.tgroup->active_threads = 0;\n#endif\n    tasklet_add(task_destroy, t);\n    t->tb.state = TASK_OVER;\n    return pid;\n}\n\nenum __ptrace_request {\n    PTRACE_TRACEME = 0,\n    PTRACE_PEEKTEXT = 1,\n    PTRACE_PEEKDATA = 2,\n    PTRACE_PEEKUSER = 3,\n    PTRACE_POKETEXT = 4,\n    PTRACE_POKEDATA = 5,\n    PTRACE_POKEUSER = 6,\n    PTRACE_CONT = 7,\n    PTRACE_KILL = 8,\n    PTRACE_SINGLESTEP = 9,\n    PTRACE_GETREGS = 12,\n    PTRACE_SETREGS = 13,\n    PTRACE_ATTACH = 16,\n    PTRACE_DETACH = 17,\n    PTRACE_SYSCALL = 24,\n    PTRACE_SEIZE = 0x4206\n};\n\nint ptrace_getregs(struct task *t, struct user *u)\n{\n    struct extra_stack_frame *cur_extra = t->tb.sp + NVIC_FRAME_SIZE + EXTRA_FRAME_SIZE;\n    struct nvic_stack_frame *cur_nvic = t->tb.sp + EXTRA_FRAME_SIZE;\n    memcpy(&u->regs[0], cur_nvic, (4 * sizeof(uint32_t))); /* r0 - r3 */\n    memcpy(&u->regs[4], cur_extra, (8 * sizeof(uint32_t))); /* r4 - r11 */\n    u->regs[12] = cur_nvic->r12;\n    u->regs[13] = (uint32_t)(t->tb.sp);\n    u->regs[14] = cur_nvic->lr;\n    u->regs[15] = cur_nvic->pc;\n    u->regs[16] = cur_nvic->psr;\n    if (t->tb.vfsi) {\n        u->tsize = t->tb.vfsi->text_size;\n        u->dsize = t->tb.vfsi->data_size;\n        u->start_code = (uint32_t)t->tb.vfsi->init;\n    }\n    u->ssize = CONFIG_TASK_STACK_SIZE;\n    u->start_stack = (uint32_t)(t->tb.cur_stack);\n    u->signal = 0;\n    u->magic = 0xd0ab1e50;\n    return 0;\n}\n\nint ptrace_peekuser(struct task *t, uint32_t addr)\n{\n    struct user u;\n    if (ptrace_getregs(t, &u) == 0)\n        return *(int *)(((char *)(&u)) + addr);\n    else return -1;\n}\n\nint ptrace_pokeuser(struct task *t, uint32_t addr, uint32_t data)\n{\n    uint32_t *cur_extra = t->tb.sp + NVIC_FRAME_SIZE + EXTRA_FRAME_SIZE;\n    uint32_t *cur_nvic = t->tb.sp + EXTRA_FRAME_SIZE;\n    int pos = addr / 4;\n\n    if (addr > (16 * sizeof(uint32_t)))\n        return -1;\n    if ((addr % 4) != 0)\n        return -1;\n    if (pos < 4) {\n        cur_nvic[pos] = data;\n        return 0;\n    }\n    if (pos < 12) {\n        cur_extra[pos - 4] = data;\n        return 0;\n    }\n    if (pos == 12) {\n        cur_nvic[4] = data;\n        return 0;\n    }\n\n    /* Breakpoints */\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n    if ((pos > 56) && (pos < 64)) {\n        pos -= 56;\n        if (data == 0)\n            return fpb_delbrk(pos);\n        return fpb_setbrk(t->tb.pid, (void *)data, pos);\n    }\n#endif\n    return -1;\n}\n\nint ptrace_setregs(struct task *t, uint32_t *regs)\n{\n    int i;\n    for (i = 0; i < 13; i++) {\n        ptrace_pokeuser(t, i * 4, regs[i]);\n    }\n    return 0;\n}\n\nint sys_ptrace_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                    uint32_t arg5)\n\n{\n    (void)arg5;\n    enum __ptrace_request request = arg1;\n    uint32_t pid = arg2;\n    void *addr = (void *)arg3;\n    void *data = (void *)arg4;\n    struct task *tracee = NULL;\n\n    /* Prepare tracee based on pid */\n    tracee = tasklist_get(&tasks_idling, pid);\n    if (!tracee)\n        tracee = tasklist_get(&tasks_running, pid);\n    if (!tracee) {\n        return -1;\n    }\n\n    switch (request) {\n    case PTRACE_TRACEME:\n        _cur_task->tb.tracer = _cur_task;\n        break;\n    case PTRACE_PEEKTEXT:\n    case PTRACE_PEEKDATA:\n        return *((uint32_t *)addr);\n\n    case PTRACE_PEEKUSER:\n        return ptrace_peekuser(tracee, (uint32_t)addr);\n    case PTRACE_POKETEXT:\n    case PTRACE_POKEDATA:\n        break;\n    case PTRACE_POKEUSER:\n        return ptrace_pokeuser(tracee, (uint32_t)addr, (uint32_t)data);\n    case PTRACE_CONT:\n        if (!tracee)\n            return -1;\n        if (tracee->tb.tracer != _cur_task)\n            return -1;\n        task_continue(tracee);\n        return 0;\n\n    case PTRACE_KILL:\n        if (!tracee)\n            return -1;\n        if (tracee->tb.tracer != _cur_task)\n            return -1;\n        task_kill(pid, SIGKILL);\n        return 0;\n\n    case PTRACE_SINGLESTEP:\n        {\n            struct user u;\n            ptrace_getregs(tracee, &u);\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n            if (fpb_setbrk(pid, (void *)((u.regs[15]) / 2 * 2 + 2), 0) >= 0) {\n                task_continue(tracee);\n                return 0;\n            } else\n#endif\n                return -1;\n        }\n\n    case PTRACE_GETREGS:\n        return ptrace_getregs(tracee, (struct user *)data);\n        break;\n    case PTRACE_SETREGS:\n        return ptrace_setregs(tracee, (uint32_t *)data);\n        break;\n\n    case PTRACE_ATTACH:\n    case PTRACE_SEIZE:\n        if (!tracee)\n            return -1;\n        tracee->tb.tracer = _cur_task;\n        if (request == PTRACE_ATTACH) {\n            task_stop(tracee);\n        }\n        return 0;\n\n    case PTRACE_DETACH:\n        if (!tracee)\n            return -1;\n        if (tracee->tb.tracer != _cur_task)\n            return -1;\n        tracee->tb.tracer = NULL;\n        task_continue(tracee);\n        return 0;\n    case PTRACE_SYSCALL:\n        if (!tracee)\n            return -1;\n        if (tracee->tb.tracer != _cur_task)\n            return -1;\n        tracee->tb.flags |= TASK_FLAG_SYSCALL_STOP;\n        return 0;\n    }\n    return -1;\n}\n\nint sys_setpriority_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3,\n                         uint32_t arg4, uint32_t arg5)\n{\n    int pid = arg2;\n    int nice = (int)arg3;\n    struct task *t = tasklist_get(&tasks_idling, pid);\n    if (!t)\n        t = tasklist_get(&tasks_running, pid);\n\n    if (arg1 != 0) /* ONLY PRIO_PROCESS IS VALID */\n        return -EINVAL;\n    if (!t)\n        return -ESRCH;\n\n    t->tb.nice = nice;\n    return 0;\n}\n\nint sys_getpriority_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3,\n                         uint32_t arg4, uint32_t arg5)\n{\n    int pid = arg2;\n    struct task *t = tasklist_get(&tasks_idling, pid);\n    if (!t)\n        t = tasklist_get(&tasks_running, pid);\n\n    if (arg1 != 0) /* ONLY PRIO_PROCESS IS VALID */\n        return -EINVAL;\n    if (!t)\n        return -ESRCH;\n\n    return (int)t->tb.nice;\n}\n\nint sys_kill_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                  uint32_t arg5)\n{\n    struct task *t = tasklist_get(&tasks_idling, arg1);\n    if (!t)\n        t = tasklist_get(&tasks_running, arg1);\n    if (!t)\n        return -ESRCH;\n    return catch_signal(t, arg2, t->tb.sigmask);\n}\n\nint task_kill(int pid, int signal)\n{\n    if (pid > 0) {\n        return sys_kill_hdlr(pid, signal, 0, 0, 0);\n    }\n}\n\nint sys_exit_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                  uint32_t arg)\n{\n    _cur_task->tb.exitval = (int)arg1;\n    task_terminate(_cur_task);\n}\n\nint sys_setsid_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                    uint32_t arg)\n{\n    int i;\n    struct filedesc_table *ft = _cur_task->tb.filedesc_table;\n    if (!ft)\n        return -1;\n    for (i = 0; (ft) && (i < ft->n_files); i++) {\n        if (ft->fdesc[i].fno != NULL) {\n            struct fnode *fno = ft->fdesc[i].fno;\n            if ((fno->flags & FL_TTY) &&\n                ((ft->fdesc[i].mask & O_NOCTTY) == 0)) {\n                struct module *mod = fno->owner;\n                if (mod && mod->ops.tty_attach) {\n                    mod->ops.tty_attach(fno, _cur_task->tb.ppid);\n                    ft->fdesc[i].mask |= O_NOCTTY;\n                    return 0;\n                }\n            }\n        }\n    }\n}\n\nint task_segfault(uint32_t address, uint32_t instruction, int flags)\n{\n    struct filedesc_table *ft;\n    if (in_kernel())\n        return -1;\n    if (_cur_task->tb.state == TASK_ZOMBIE)\n        return 0;\n\n    ft = _cur_task->tb.filedesc_table;\n    if (ft && (ft->n_files > 2) && ft->fdesc[2].fno->owner->ops.write) {\n#ifdef CONFIG_EXTENDED_MEMFAULT\n        char segv_msg[128] = \"Memory fault: process (pid=\";\n        strcat(segv_msg, pid_str(_cur_task->tb.pid));\n        if (flags == MEMFAULT_ACCESS) {\n            strcat(segv_msg, \") attempted access to memory at \");\n            strcat(segv_msg, x_str(address));\n        }\n        if (flags == MEMFAULT_DOUBLEFREE) {\n            strcat(segv_msg, \") attempted double free\");\n        }\n        strcat(segv_msg, \". Killed.\\r\\n\");\n#else\n        char segv_msg[] = \">_< -- Segfault -- >_<\";\n#endif\n        ft->fdesc[2].fno->owner->ops.write(ft->fdesc[2].fno, segv_msg,\n                                           strlen(segv_msg));\n    }\n    task_terminate(_cur_task);\n    return 0;\n}\n\nint task_ptr_valid(const void *ptr)\n{\n    struct task *t;\n    uint8_t *stack_start = (uint8_t *)_cur_task->tb.cur_stack;\n    uint8_t *stack_end = stack_start + SCHEDULER_STACK_SIZE;\n\n    if (!ptr)\n        return 0; /* NULL is a permitted value */\n\n    if (_cur_task->tb.pid == 0)\n        return 0; /* Kernel mode */\n    if (((uint8_t *)ptr >= stack_start) && ((uint8_t *)ptr < stack_end))\n        return 0; /* In the process own's  stack */\n    if (fmalloc_owner(ptr) == _cur_task->tb.pid)\n        return 0; /* In the process own's  heap */\n\n    t = tasklist_get(&tasks_idling, _cur_task->tb.ppid);\n    if (t && (t->tb.state == TASK_FORKED)) {\n        /* execution after fork(), parent memory allowed. */\n        if (fmalloc_owner(ptr) == _cur_task->tb.ppid)\n            return 0; /* In the process parent's  heap */\n    }\n    return -1;\n}\n\n#pragma GCC push_options\n#pragma GCC optimize (\"O0\")\nstruct nvic_stack_frame *n_stack = NULL;\nstatic uint32_t *a0 = NULL;\nstatic uint32_t *a1 = NULL;\nstatic uint32_t *a2 = NULL;\nstatic uint32_t *a3 = NULL;\nstatic uint32_t *a4 = NULL;\nstatic uint32_t *a5 = NULL;\n\nint __naked sv_call_handler(void)\n{\n    irq_off();\n\n    save_task_context();\n    asm volatile(\"mrs %0, \" PSP \"\" : \"=r\"(_top_stack));\n\n    /* save current SP to TCB */\n    _cur_task->tb.sp = _top_stack;\n\n    /* Get function arguments */\n    n_stack = (struct nvic_stack_frame *)(_cur_task->tb.sp + NVIC_FRAME_SIZE);\n    a0 = &n_stack->r0;\n    a1 = &n_stack->r1;\n    a2 = &n_stack->r2;\n    a3 = &n_stack->r3;\n    a4 = (uint32_t *)((uint8_t *)_cur_task->tb.sp +\n                      (EXTRA_FRAME_SIZE + NVIC_FRAME_SIZE + 8*4));\n    a5 = (uint32_t *)((uint8_t *)_cur_task->tb.sp +\n                      (EXTRA_FRAME_SIZE + NVIC_FRAME_SIZE + 8*4 + 4));\n\n\n    if (*a0 == SV_CALL_SIGRETURN) {\n        uint32_t *syscall_retval =\n            (uint32_t *)(_cur_task->tb.osp + EXTRA_FRAME_SIZE);\n        _cur_task->tb.sp = _cur_task->tb.osp;\n        _cur_task->tb.flags &= (~(TASK_FLAG_SIGNALED));\n        if (*syscall_retval == SYS_CALL_AGAIN_VAL) {\n            *syscall_retval = -EINTR;\n        }\n        irq_on();\n        goto return_from_syscall;\n    }\n    if (*a0 >= _SYSCALLS_NR) {\n        restore_task_context();\n        irq_on();\n        return -1;\n    }\n    if (sys_syscall_handlers[*a0] == NULL) {\n        restore_task_context();\n        irq_on();\n        return -1;\n    }\n\n#ifdef CONFIG_SYSCALL_TRACE\n    Strace[StraceTop].n = n;\n    Strace[StraceTop].pid = _cur_task->tb.pid;\n    Strace[StraceTop].sp = (uint32_t)_top_stack;\n    StraceTop++;\n    if (StraceTop > 9)\n        StraceTop = 0;\n#endif\n\n    /* Execute syscall */\n    int (*call)(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4,\n                uint32_t arg5) = NULL;\n\n    _cur_task->tb.flags |= TASK_FLAG_IN_SYSCALL;\n    call = sys_syscall_handlers[*a0];\n    if (!call) {\n        irq_on();\n        goto return_from_syscall;\n    }\n    call(*a1, *a2, *a3, *a4, *a5);\n\n    /* Exec does not have a return value, and will use r0 as args for main()*/\n    if (call != sys_syscall_handlers[SYS_EXEC])\n        asm volatile(\n            \"mov %0, r0\"\n            : \"=r\"(*((uint32_t *)(_cur_task->tb.sp + EXTRA_FRAME_SIZE))));\n\n    /* out of syscall */\n    _cur_task->tb.flags &= (~TASK_FLAG_IN_SYSCALL);\n    irq_on();\n\n    if (_cur_task->tb.state != TASK_RUNNING) {\n        task_switch();\n    }\n\nreturn_from_syscall:\n\n    /* write new stack pointer and restore context */\n    if (in_kernel()) {\n        asm volatile(\"msr \" MSP \", %0\" ::\"r\"(_cur_task->tb.sp));\n        asm volatile(\"isb\");\n        restore_kernel_context();\n        runnable = RUN_KERNEL;\n    } else {\n        mpu_task_on((void *)(((uint32_t)_cur_task->tb.cur_stack) -\n                             (sizeof(struct task_block) + F_MALLOC_OVERHEAD)));\n        asm volatile(\"msr \" PSP \", %0\" ::\"r\"(_cur_task->tb.sp));\n        asm volatile(\"isb\");\n        restore_task_context();\n        runnable = RUN_USER;\n    }\n\n    /* Set control bit for non-kernel threads */\n    if (_cur_task->tb.pid != 0) {\n        asm volatile(\"msr CONTROL, %0\" ::\"r\"(0x01));\n    } else {\n        asm volatile(\"msr CONTROL, %0\" ::\"r\"(0x00));\n    }\n    asm volatile(\"isb\");\n\n    /* Set return value selected by the restore procedure */\n    asm volatile(\"mov lr, %0\" ::\"r\"(runnable));\n\n    /* return (function is naked) */\n    asm volatile(\"bx lr\");\n}\n\n#pragma GCC pop_options\n"
  },
  {
    "path": "kernel/scheduler.h",
    "content": "#ifndef INCLUDED_SCHEDULER_H\n#define INCLUDED_SCHEDULER_H\n#include \"vfs.h\"\n\n#endif\n"
  },
  {
    "path": "kernel/semaphore.S",
    "content": "\n.syntax unified\n\n/* Try to decrease the semaphore. \n * On success, return 0. \n * On failure, return -1 (sem == 0, try again later).\n */\n\n.global _sem_wait\n_sem_wait:\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   LDREX   r1, [r0]\n#elif defined(__ARM_ARCH_6M__)\n  CPSID    i\n  LDR      r1, [r0]\n#endif\n   CMP      r1, #0           // Test if semaphore holds the value 0\n   BEQ     _sem_wait_fail    // If it does, return 0\n   SUBS    r1, #1            // If not, decrement temporary copy\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   STREX   r2, r1, [r0]      // Attempt Store-Exclusive\n   CMP     r2, #0            // Check if Store-Exclusive succeeded\n   BNE     _sem_wait         // If Store-Exclusive failed, retry from start\n   DMB                       // Required before accessing protected resource\n#elif defined(__ARM_ARCH_6M__)\n   STR     r1, [r0]\n   CPSIE   i\n#endif\n   MOVS    r0, #0            // Successfully acquired.\n   BX      lr\n_sem_wait_fail:\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   DMB\n   MOV     r0, #-1           // Already locked!\n#elif defined(__ARM_ARCH_6M__)\n   CPSIE   i\n   MOVS    r2, #0            // Already locked!\n   MVNS    r0, r2\n#endif\n   BX      lr\n\n/* Increase the semaphore value. \n * If the value was 0, return 1 (send a signal to the listeners)\n * If a non-zero semaphore is incremented, return 0. (do not signal).\n */\n\n.global _sem_post\n_sem_post:\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   LDREX   r1, [r0]\n#elif defined(__ARM_ARCH_6M__)\n   CPSID    i\n   LDR      r1, [r0]\n#endif\n   ADDS    r1, #1           // Increment temporary copy\n#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)\n   STREX   r2, r1, [r0]     // Attempt Store-Exclusive\n   CMP     r2, #0           // Check if Store-Exclusive succeeded\n   BNE     _sem_post        // Store failed - retry immediately\n#elif defined(__ARM_ARCH_6M__)\n   STR     r1, [r0]\n   CPSIE   i\n#endif\n   CMP     r0, #1           // Store successful - test if incremented from zero\n   DMB                      // Required before releasing protected resource\n   BGE     _sem_signal_up   // If initial value was 0, signal update\n   MOVS    r0, #0\n   BX      lr\n_sem_signal_up:\n   MOVS    r0, #1           // Semaphore was 0, send a signal to listeners.\n   BX      lr\n\n"
  },
  {
    "path": "kernel/stm32f4/Kconfig",
    "content": "if ARCH_STM32F4\n\nchoice \n    prompt \"MCU\"\n    default ARCH_STM32F407_XG\n\nconfig ARCH_STM32F401_XB\n    bool \"STM32F401xB 128KB\"\n    select FLASH_SIZE_128KB\n    select RAM_SIZE_64KB\n    select ARCH_STM32F401\nconfig ARCH_STM32F401_XC\n    bool \"STM32F401xC 256KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_64KB\n    select ARCH_STM32F401\nconfig ARCH_STM32F401_XD\n    bool \"STM32F401xD 384KB\"\n    select FLASH_SIZE_384KB\n    select RAM_SIZE_96KB\n    select ARCH_STM32F401\nconfig ARCH_STM32F401_XE\n    bool \"STM32F401xE 512KB\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_96KB\n    select ARCH_STM32F401\n\nconfig ARCH_STM32F405_XG\n    bool \"STM32F405xG 1MB\"\n    select FLASH_SIZE_1MB\n    select RAM_SIZE_192KB\n    select ARCH_STM32F405\nconfig ARCH_STM32F405_XE\n    bool \"STM32F407xE 512KB\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_192KB\n    select ARCH_STM32F405\n\nconfig ARCH_STM32F407_XG\n    bool \"STM32F407xG 1MB\"\n    select FLASH_SIZE_1MB\n    select RAM_SIZE_192KB\n    select ARCH_STM32F407\nconfig ARCH_STM32F407_XE\n    bool \"STM32F407xE 512KB\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_192KB\n    select ARCH_STM32F407\n    \nconfig ARCH_STM32F411_XE\n    bool \"STM32F411xE 512KB\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_128KB\n    select ARCH_STM32F411\nconfig ARCH_STM32F411_XC\n    bool \"STM32F411xC 256KB\"\n    select FLASH_SIZE_256KB\n    select RAM_SIZE_128KB\n    select ARCH_STM32F411\n\nconfig ARCH_STM32F429_XE\n    bool \"STM32F429xE 512KB\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_256KB\n    select ARCH_STM32F429\nconfig ARCH_STM32F429_XG\n    bool \"STM32F429xG 1MB\"\n    select FLASH_SIZE_1MB\n    select RAM_SIZE_256KB\n    select ARCH_STM32F429\nconfig ARCH_STM32F429_XI\n    bool \"STM32F429xI 2MB\"\n    select FLASH_SIZE_2MB\n    select RAM_SIZE_256KB\n    select ARCH_STM32F429\nconfig ARCH_STM32F446_ZE\n    bool \"STM32F446ZE 512KB\"\n    select FLASH_SIZE_512KB\n    select RAM_SIZE_128KB\n    select ARCH_STM32F446\nendchoice\n\nendif\n"
  },
  {
    "path": "kernel/stm32f4/stm32f4.ld.in",
    "content": "MEMORY\n{\n    FLASH (rx) : ORIGIN = __FLASH_ORIGIN, LENGTH = __KFLASHMEM_SIZE\n    SRAM (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __KRAMMEM_SIZE\n    SRAM_USER (rwx) : ORIGIN = (__RAM1_BASE + __KRAMMEM_SIZE), LENGTH = (__RAM1_SIZE - __KRAMMEM_SIZE)\n    SRAM_EXTRA (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE\n    SDRAM_USER(rwx) : ORIGIN = __SDRAM_BASE, LENGTH = __SDRAM_SIZE\n}\n\n /* Enforce emmition of the vector table. */\nEXTERN (vector_table)\n\n/* Define the entry point of the output file. */\nENTRY(reset_handler)\n\nSECTIONS\n{\n    .text :\n    {\n        KEEP(*(.vectors))\n        *(.text*)\n        *(.rodata*)\n    } > FLASH\n\t/* C++ Static constructors/destructors, also used for __attribute__\n\t * ((constructor)) and the likes */\n\t.preinit_array : {\n\t\t. = ALIGN(4);\n\t\t__preinit_array_start = .;\n\t\tKEEP (*(.preinit_array))\n\t\t__preinit_array_end = .;\n\t} > FLASH\n\t.init_array : {\n\t\t. = ALIGN(4);\n\t\t__init_array_start = .;\n\t\tKEEP (*(SORT(.init_array.*)))\n\t\tKEEP (*(.init_array))\n\t\t__init_array_end = .;\n\t} > FLASH\n\t.fini_array : {\n\t\t. = ALIGN(4);\n\t\t__fini_array_start = .;\n\t\tKEEP (*(.fini_array))\n\t\tKEEP (*(SORT(.fini_array.*)))\n\t\t__fini_array_end = .;\n\t} > FLASH\n \n    .data :\n    {\n        _etext = LOADADDR(.data);\n        _data = .;\n        *(vtable)\n        *(.data*)\n        _edata = .;\n    } > SRAM AT > FLASH\n\t_data_loadaddr = LOADADDR(.data);\n \n    .bss :\n    {\n        _bss = .;\n        *(.bss*)\n        *(COMMON)\n        . = ALIGN(32 / 8);\n        _ebss = .;\n        PROVIDE (end = .);\n    } > SRAM\n\n    .heap :\n    {\n        /* heap starts after BSS */\n        PROVIDE(_heap_start = _ebss );\n    } > SRAM\n}\n\nPROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));\nPROVIDE(_user_heap_start = ORIGIN(SRAM_USER));\nPROVIDE(_user_heap_end = ORIGIN(SRAM_USER) + LENGTH(SRAM_USER));\nPROVIDE(_extra_heap_start = ORIGIN(SRAM_EXTRA));\nPROVIDE(_extra_heap_end = ORIGIN(SRAM_EXTRA) + LENGTH(SRAM_EXTRA));\nPROVIDE(_external_heap_start = ORIGIN(SDRAM_USER));\nPROVIDE(_external_heap_end = ORIGIN(SDRAM_USER) + LENGTH(SDRAM_USER));\n\n"
  },
  {
    "path": "kernel/stm32f4/stm32f407discovery.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include <unicore-mx/cm3/systick.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/usart.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/sdio.h>\n#include <unicore-mx/stm32/i2c.h>\n#include <unicore-mx/stm32/dma.h>\n#include \"unicore-mx/stm32/spi.h\"\n#include \"drivers/stm32_sdio.h\"\n\n#include \"uart.h\"\n#include \"gpio.h\"\n#include \"sdio.h\"\n#include \"dsp.h\"\n#include \"rng.h\"\n#include \"usb.h\"\n#include \"eth.h\"\n#include \"i2c.h\"\n#include \"spi.h\"\n#include \"dsp.h\"\n#include \"dma.h\"\n#include \"drivers/lis3dsh.h\"\n\nextern int xadow_led_init(uint32_t bus);\n\n#if CONFIG_SYS_CLOCK == 48000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_48MHZ\n#elif CONFIG_SYS_CLOCK == 84000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_84MHZ\n#elif CONFIG_SYS_CLOCK == 100000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_100MHZ\n#elif CONFIG_SYS_CLOCK == 120000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_120MHZ\n#elif CONFIG_SYS_CLOCK == 168000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_168MHZ\n#else\n#   error No valid clock speed selected\n#endif\n\nstatic const struct gpio_config Led[4] = {\n    {\n        .base=GPIOD,\n        .pin=GPIO12,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led0\"\n    },\n    {\n        .base=GPIOD,\n        .pin=GPIO13,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led1\"\n    },\n    {\n        .base=GPIOD,\n        .pin=GPIO14,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led2\"\n    },\n    {\n        .base=GPIOD,\n        .pin=GPIO15,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led3\"\n    },\n};\n\nstatic const struct gpio_config Button = {\n    .base=GPIOA,\n    .pin=GPIO0,\n    .mode=GPIO_MODE_INPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_NONE,\n    .name=\"button\"\n};\n\nstatic struct usb_pio_config_fs pio_fs = {\n    .pio_vbus = {\n        .base=GPIOA,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dm =   {\n        .base=GPIOA,\n        .pin=GPIO11,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dp =   {\n        .base=GPIOA,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    }\n};\n\nstatic struct usb_config usb_guest = {\n    .dev_type = USB_DEV_FS,\n    .otg_mode = USB_MODE_GUEST,\n    .pio.fs = &pio_fs\n};\n\n\nconst struct gpio_config stm32eth_mii_pins[] = {\n    {.base=GPIOA, .pin=GPIO2, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDIO\n    {.base=GPIOC, .pin=GPIO1, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDC\n    {.base=GPIOA, .pin=GPIO1, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII REF CLK\n    {.base=GPIOA, .pin=GPIO7, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII CRS DV\n    {.base=GPIOB, .pin=GPIO10,.mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXER\n    {.base=GPIOC, .pin=GPIO4, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD0\n    {.base=GPIOC, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD1\n    {.base=GPIOB, .pin=GPIO11,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXEN\n    {.base=GPIOB, .pin=GPIO12,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD0\n    {.base=GPIOB, .pin=GPIO13,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD1\n};\n\nstatic const struct eth_config eth_config = {\n    .pio_mii = stm32eth_mii_pins,\n    .n_pio_mii = 10,\n    .pio_phy_reset = {\n        .base=GPIOE,\n        .pin=GPIO2,\n        .mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .has_phy_reset = 1\n};\n\n\nstatic const struct i2c_config i2c_configs[] = {\n#ifdef CONFIG_I2C1\n    {\n        .idx  = 1,\n        .base = I2C1,\n        .ev_irq = NVIC_I2C1_EV_IRQ,\n        .er_irq = NVIC_I2C1_ER_IRQ,\n        .rcc = RCC_I2C1,\n        .dma_rcc = RCC_DMA1,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM6,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM6_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM5,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM5_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOB,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n        .pio_sda = {\n            .base=GPIOB,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n    },\n#endif\n};\n#define NUM_I2CS (sizeof(i2c_configs) / sizeof(struct i2c_config))\n\nstatic const struct spi_config spi_configs[] = {\n#ifdef CONFIG_SPI_1\n    {\n        .idx  = 1,\n        .base = SPI1,\n        .irq = NVIC_SPI1_IRQ,\n        .rcc = RCC_SPI1,\n        .baudrate = 0, /* TODO: SPI baudrate */\n        .polarity = 1,\n        .phase = 1,\n        .rx_only = 0,\n        .bidir_mode = 0,\n        .dff_16 = 0,\n        .enable_software_slave_management = 1,\n        .send_msb_first = 1,\n\n        .tx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM3,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &SPI_DR(SPI1),\n            .irq = 0,\n        },\n        .rx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &SPI_DR(SPI1),\n            .irq = NVIC_DMA2_STREAM2_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_sck = {\n            .base=GPIOA,\n            .pin=GPIO5,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_mosi = {\n            .base=GPIOA,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_miso = {\n            .base=GPIOA,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n    },\n#endif\n#ifdef CONFIG_SPI_3\n    {\n        .idx  = 3,\n        .base = SPI1,\n        .irq = NVIC_SPI3_IRQ,\n        .rcc = RCC_SPI3,\n        .baudrate = 0, /* TODO: SPI baudrate */\n        .polarity = 1,\n        .phase = 1,\n        .rx_only = 0,\n        .bidir_mode = 0,\n        .dff_16 = 0,\n        .enable_software_slave_management = 1,\n        .send_msb_first = 1,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM5,\n            .channel = DMA_SxCR_CHSEL_0,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &SPI_DR(SPI3),\n            .irq = 0,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM0,\n            .channel = DMA_SxCR_CHSEL_0,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &SPI_DR(SPI3),\n            .irq = NVIC_DMA1_STREAM0_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_sck = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_mosi = {\n            .base=GPIOC,\n            .pin=GPIO12,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_miso = {\n            .base=GPIOC,\n            .pin=GPIO11,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_nss = {\n            .base=GPIOA,\n            .pin=GPIO4,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n    },\n#endif\n};\n#define NUM_SPIS (sizeof(spi_configs) / sizeof(struct spi_config))\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_1\n    {   .devidx = 1,\n        .base = USART1,\n        .irq = NVIC_USART1_IRQ,\n        .rcc = RCC_USART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = USART2,\n        .irq = NVIC_USART2_IRQ,\n        .rcc = RCC_USART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO2,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO3,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_3\n    {\n        .devidx = 3,\n        .base = USART3,\n        .irq = NVIC_USART3_IRQ,\n        .rcc = RCC_USART3,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {\n            .base=GPIOD,\n            .pin=GPIO8,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n        .pio_tx = {\n            .base=GPIOD,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_6\n    {\n        .devidx = 6,\n        .base = USART6,\n        .irq = NVIC_USART6_IRQ,\n        .rcc = RCC_USART6,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOC,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n        .pio_tx = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\n/* Setup GPIO Pins for SDIO:\n   PC8 - PC11 - DAT0 thru DAT3\n   PC12 - CLK\n   PD2 - CMD\n*/\nstruct sdio_config sdio_conf = {\n    .devidx = 0,\n    .base = SDIO_BASE,\n    .rcc_reg = (uint32_t *)&RCC_APB2ENR,\n    .rcc_en  = RCC_APB2ENR_SDIOEN,\n    .rcc_rst_reg = (uint32_t *)&RCC_APB2RSTR,\n    .rcc_rst  = RCC_APB2RSTR_SDIORST,\n    .card_detect_supported = 0,\n    .pio_dat0 = {\n        .base=GPIOC,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .af = GPIO_AF12,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n\n    },\n    .pio_dat1 = {\n        .base=GPIOC,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat2 = {\n        .base=GPIOC,\n        .pin=GPIO10,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat3 = {\n        .base=GPIOC,\n        .pin=GPIO11,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_clk = {\n        .base=GPIOC,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cmd = {\n        .base=GPIOD,\n        .pin=GPIO2,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n};\n\nstruct gpio_config lis3dsh_pio = {\n    .base=GPIOE,\n    .pin=GPIO3,\n    .mode=GPIO_MODE_OUTPUT,\n    .pullupdown=GPIO_PUPD_PULLUP\n};\n\n\nint machine_init(void)\n{\n    int i;\n    /* Clock */\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[STM32_CLOCK]);\n\n    /* Leds */\n    for (i = 0; i < 4; i++) {\n        gpio_create(NULL, &Led[i]);\n    }\n\n    /* Button */\n    gpio_create(NULL, &Button);\n\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n\n    /* I2Cs */\n    for (i = 0; i < NUM_I2CS; i++) {\n        i2c_create(&i2c_configs[i]);\n    }\n\n    /* SPIs */\n    for (i = 0; i < NUM_SPIS; i++) {\n        devspi_create(&spi_configs[i]);\n    }\n\n    lis3dsh_init(1, &lis3dsh_pio);\n\n    rng_create(1, RCC_RNG);\n    sdio_conf.rcc_reg = (uint32_t *)&RCC_APB2ENR;\n    sdio_conf.rcc_en  = RCC_APB2ENR_SDIOEN;\n    sdio_init(&sdio_conf);\n    usb_init(&usb_guest);\n    ethernet_init(&eth_config);\n    dsp_init();\n    #ifdef CONFIG_DEVMCCOG21\n    mccog21_init(1);\n    #endif\n    #ifdef CONFIG_DEVXALED5X7\n    xadow_led_init(1);\n    #endif\n\n    #ifdef CONFIG_DEVCS43L22\n    cs43l22_init(1);\n    #endif\n\n    return 0;\n}\n"
  },
  {
    "path": "kernel/stm32f4/stm32f407diymore.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include <unicore-mx/cm3/systick.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/usart.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/sdio.h>\n#include <unicore-mx/stm32/i2c.h>\n#include <unicore-mx/stm32/dma.h>\n#include \"unicore-mx/stm32/spi.h\"\n#include \"drivers/stm32_sdio.h\"\n\n#include \"uart.h\"\n#include \"gpio.h\"\n#include \"sdio.h\"\n#include \"dsp.h\"\n#include \"rng.h\"\n#include \"usb.h\"\n#include \"eth.h\"\n#include \"i2c.h\"\n#include \"spi.h\"\n#include \"dsp.h\"\n#include \"dma.h\"\n#include \"drivers/lis3dsh.h\"\n\nextern int xadow_led_init(uint32_t bus);\n\n#if CONFIG_SYS_CLOCK == 48000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_48MHZ\n#elif CONFIG_SYS_CLOCK == 84000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_84MHZ\n#elif CONFIG_SYS_CLOCK == 100000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_100MHZ\n#elif CONFIG_SYS_CLOCK == 120000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_120MHZ\n#elif CONFIG_SYS_CLOCK == 168000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_168MHZ\n#else\n#   error No valid clock speed selected\n#endif\n\nstatic const struct gpio_config Led = {\n    .base=GPIOE,\n    .pin=GPIO0,.mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_PULLUP,\n    .name=\"led0\"\n};\n\nstatic const struct gpio_config Button = {\n    .base=GPIOD,\n    .pin=GPIO15,\n    .mode=GPIO_MODE_INPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_NONE,\n    .name=\"button\"\n};\n\nstatic struct usb_pio_config_fs pio_fs = {\n    .pio_vbus = {\n        .base=GPIOA,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dm =   {\n        .base=GPIOA,\n        .pin=GPIO11,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dp =   {\n        .base=GPIOA,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    }\n};\n\nstatic struct usb_config usb_guest = {\n    .dev_type = USB_DEV_FS,\n    .otg_mode = USB_MODE_GUEST,\n    .pio.fs = &pio_fs\n};\n\n\nstatic const struct i2c_config i2c_configs[] = {\n#ifdef CONFIG_I2C1\n    {\n        .idx  = 1,\n        .base = I2C1,\n        .ev_irq = NVIC_I2C1_EV_IRQ,\n        .er_irq = NVIC_I2C1_ER_IRQ,\n        .rcc = RCC_I2C1,\n        .dma_rcc = RCC_DMA1,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM6,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM6_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM5,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM5_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOB,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n        .pio_sda = {\n            .base=GPIOB,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n    },\n#endif\n};\n#define NUM_I2CS (sizeof(i2c_configs) / sizeof(struct i2c_config))\n\nstatic const struct spi_config spi_configs[] = {\n#ifdef CONFIG_SPI_1\n    {\n        .idx  = 1,\n        .base = SPI1,\n        .irq = NVIC_SPI1_IRQ,\n        .rcc = RCC_SPI1,\n        .baudrate = 0, /* TODO: SPI baudrate */\n        .polarity = 1,\n        .phase = 1,\n        .rx_only = 0,\n        .bidir_mode = 0,\n        .dff_16 = 0,\n        .enable_software_slave_management = 1,\n        .send_msb_first = 1,\n\n        .tx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM3,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &SPI_DR(SPI1),\n            .irq = 0,\n        },\n        .rx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &SPI_DR(SPI1),\n            .irq = NVIC_DMA2_STREAM2_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_sck = {\n            .base=GPIOA,\n            .pin=GPIO5,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_mosi = {\n            .base=GPIOA,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_miso = {\n            .base=GPIOA,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n    },\n#endif\n#ifdef CONFIG_SPI_3\n    {\n        .idx  = 3,\n        .base = SPI1,\n        .irq = NVIC_SPI3_IRQ,\n        .rcc = RCC_SPI3,\n        .baudrate = 0, /* TODO: SPI baudrate */\n        .polarity = 1,\n        .phase = 1,\n        .rx_only = 0,\n        .bidir_mode = 0,\n        .dff_16 = 0,\n        .enable_software_slave_management = 1,\n        .send_msb_first = 1,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM5,\n            .channel = DMA_SxCR_CHSEL_0,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &SPI_DR(SPI3),\n            .irq = 0,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM0,\n            .channel = DMA_SxCR_CHSEL_0,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &SPI_DR(SPI3),\n            .irq = NVIC_DMA1_STREAM0_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_sck = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_mosi = {\n            .base=GPIOC,\n            .pin=GPIO12,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_miso = {\n            .base=GPIOC,\n            .pin=GPIO11,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_nss = {\n            .base=GPIOA,\n            .pin=GPIO4,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n    },\n#endif\n};\n#define NUM_SPIS (sizeof(spi_configs) / sizeof(struct spi_config))\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_1\n    {   .devidx = 1,\n        .base = USART1,\n        .irq = NVIC_USART1_IRQ,\n        .rcc = RCC_USART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = USART2,\n        .irq = NVIC_USART2_IRQ,\n        .rcc = RCC_USART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO2,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO3,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\nint machine_init(void)\n{\n    int i;\n    /* Clock */\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[STM32_CLOCK]);\n\n    /* Leds */\n    gpio_create(NULL, &Led);\n\n    /* Button */\n    gpio_create(NULL, &Button);\n\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n\n    /* I2Cs */\n    for (i = 0; i < NUM_I2CS; i++) {\n        i2c_create(&i2c_configs[i]);\n    }\n\n    usb_init(&usb_guest);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/stm32f4/stm32f411nucleo.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include <unicore-mx/cm3/systick.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/usart.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/i2c.h>\n#include <unicore-mx/stm32/dma.h>\n#include \"unicore-mx/stm32/spi.h\"\n\n#include \"uart.h\"\n#include \"gpio.h\"\n#include \"dsp.h\"\n#include \"rng.h\"\n#include \"usb.h\"\n#include \"i2c.h\"\n#include \"dma.h\"\n#include \"spi.h\"\n#include \"drivers/lis3dsh.h\"\n\nextern int xadow_led_init(uint32_t bus);\n\n#if CONFIG_SYS_CLOCK == 48000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_48MHZ\n#elif CONFIG_SYS_CLOCK == 84000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_84MHZ\n#elif CONFIG_SYS_CLOCK == 100000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_100MHZ\n#elif CONFIG_SYS_CLOCK == 120000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_120MHZ\n#elif CONFIG_SYS_CLOCK == 168000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_168MHZ\n#else\n#   error No valid clock speed selected\n#endif\n\nstatic const struct gpio_config Led = {\n    .base=GPIOA,\n    .pin=GPIO5,.mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led0\"\n};\n\nstatic const struct gpio_config Button = {\n    .base=GPIOC,\n    .pin=GPIO13,\n    .mode=GPIO_MODE_INPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_NONE,\n    .name=\"button\"\n};\n\nstatic struct usb_pio_config_fs pio_fs = {\n    .pio_vbus = {\n        .base=GPIOA,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dm =   {\n        .base=GPIOA,\n        .pin=GPIO11,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dp =   {\n        .base=GPIOA,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    }\n};\n\nstatic struct usb_config usb_guest = {\n    .dev_type = USB_DEV_FS,\n    .otg_mode = USB_MODE_GUEST,\n    .pio.fs = &pio_fs\n};\n\n\nstatic const struct i2c_config i2c_configs[] = {\n#ifdef CONFIG_I2C1\n    {\n        .idx  = 1,\n        .base = I2C1,\n        .ev_irq = NVIC_I2C1_EV_IRQ,\n        .er_irq = NVIC_I2C1_ER_IRQ,\n        .rcc = RCC_I2C1,\n        .dma_rcc = RCC_DMA2,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM6,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM6_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM0,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM0_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOB,\n            .pin=GPIO8,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n        .pio_sda = {\n            .base=GPIOB,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_I2C2\n    {\n        .idx  = 1,\n        .base = I2C2,\n        .ev_irq = NVIC_I2C2_EV_IRQ,\n        .er_irq = NVIC_I2C2_ER_IRQ,\n        .rcc = RCC_I2C2,\n        .dma_rcc = RCC_DMA1,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM7,\n            .channel = DMA_SxCR_CHSEL_7,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C2),\n            .irq = NVIC_DMA1_STREAM7_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_7,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C2),\n            .irq = NVIC_DMA1_STREAM7_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOB,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n        .pio_sda = {\n            .base=GPIOB,\n            .pin=GPIO3,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF9,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_I2C3\n    {\n        .idx  = 2,\n        .base = I2C3,\n        .ev_irq = NVIC_I2C2_EV_IRQ,\n        .er_irq = NVIC_I2C2_ER_IRQ,\n        .rcc = RCC_I2C2,\n        .dma_rcc = RCC_DMA1,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM7,\n            .channel = DMA_SxCR_CHSEL_7,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C2),\n            .irq = NVIC_DMA1_STREAM7_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_7,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C2),\n            .irq = NVIC_DMA1_STREAM7_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOA,\n            .pin=GPIO8,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n        .pio_sda = {\n            .base=GPIOC,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n    },\n#endif\n};\n#define NUM_I2CS (sizeof(i2c_configs) / sizeof(struct i2c_config))\n\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_1\n    {   .devidx = 1,\n        .base = USART1,\n        .irq = NVIC_USART1_IRQ,\n        .rcc = RCC_USART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = USART2,\n        .irq = NVIC_USART2_IRQ,\n        .rcc = RCC_USART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO3,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO2,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_6\n    {\n        .devidx = 6,\n        .base = USART6,\n        .irq = NVIC_USART6_IRQ,\n        .rcc = RCC_USART6,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n        .pio_tx = {\n            .base=GPIOC,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\nstatic const struct spi_config spi_configs[] = {\n#ifdef CONFIG_SPI_1\n    {\n        .idx  = 1,\n        .base = SPI1,\n        .irq = NVIC_SPI1_IRQ,\n        .rcc = RCC_SPI1,\n        .baudrate = 0, /* TODO: SPI baudrate */\n        .polarity = 1,\n        .phase = 1,\n        .rx_only = 0,\n        .bidir_mode = 0,\n        .dff_16 = 0,\n        .enable_software_slave_management = 1,\n        .send_msb_first = 1,\n\n        .tx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM3,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &SPI_DR(SPI1),\n            .irq = 0,\n        },\n        .rx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &SPI_DR(SPI1),\n            .irq = NVIC_DMA2_STREAM2_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_sck = {\n            .base=GPIOA,\n            .pin=GPIO5,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_mosi = {\n            .base=GPIOA,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_miso = {\n            .base=GPIOA,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n    },\n#endif\n#ifdef CONFIG_SPI_3\n    {\n        .idx  = 3,\n        .base = SPI1,\n        .irq = NVIC_SPI3_IRQ,\n        .rcc = RCC_SPI3,\n        .baudrate = 0, /* TODO: SPI baudrate */\n        .polarity = 1,\n        .phase = 1,\n        .rx_only = 0,\n        .bidir_mode = 0,\n        .dff_16 = 0,\n        .enable_software_slave_management = 1,\n        .send_msb_first = 1,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM5,\n            .channel = DMA_SxCR_CHSEL_0,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &SPI_DR(SPI3),\n            .irq = 0,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM0,\n            .channel = DMA_SxCR_CHSEL_0,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &SPI_DR(SPI3),\n            .irq = NVIC_DMA1_STREAM0_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_sck = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_mosi = {\n            .base=GPIOC,\n            .pin=GPIO12,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_miso = {\n            .base=GPIOC,\n            .pin=GPIO11,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_nss = {\n            .base=GPIOA,\n            .pin=GPIO4,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF6,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n    },\n#endif\n};\n#define NUM_SPIS (sizeof(spi_configs) / sizeof(struct spi_config))\n\nint machine_init(void)\n{\n    int i;\n    /* Clock */\n\n#ifdef CLOCK_12MHZ\n    rcc_clock_setup_hse_3v3(&rcc_hse_12mhz_3v3[STM32_CLOCK]);\n#else\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[STM32_CLOCK]);\n#endif\n\n    /* Leds */\n    for (i = 0; i < 4; i++) {\n        gpio_create(NULL, &Led);\n    }\n\n    /* Button */\n    gpio_create(NULL, &Button);\n\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n\n    /* I2Cs */\n    for (i = 0; i < NUM_I2CS; i++) {\n        i2c_create(&i2c_configs[i]);\n    }\n    \n    /* SPIs */\n    for (i = 0; i < NUM_SPIS; i++) {\n        devspi_create(&spi_configs[i]);\n    }\n\n    rng_create(1, RCC_RNG);\n    usb_init(&usb_guest);\n    #ifdef CONFIG_DEVMCCOG21\n    mccog21_init(1);\n    #endif\n    #ifdef CONFIG_DEVXALED5X7\n    xadow_led_init(1);\n    #endif\n    return 0;\n}\n"
  },
  {
    "path": "kernel/stm32f4/stm32f429discovery.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent, brabo\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include \"unicore-mx/stm32/usart.h\"\n#include \"unicore-mx/cm3/nvic.h\"\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/i2c.h>\n#include <unicore-mx/stm32/spi.h>\n#include <unicore-mx/stm32/dma.h>\n#include \"gpio.h\"\n#include \"stmpe811.h\"\n#include \"uart.h\"\n#include \"rng.h\"\n#include \"i2c.h\"\n#include \"spi.h\"\n\n\n\n\n#if CONFIG_SYS_CLOCK == 48000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_48MHZ\n#elif CONFIG_SYS_CLOCK == 84000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_84MHZ\n#elif CONFIG_SYS_CLOCK == 120000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_120MHZ\n#elif CONFIG_SYS_CLOCK == 168000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_168MHZ\n#else\n#   error No valid clock speed selected\n#endif\n\nstatic const struct gpio_config Led0 = {\n    .base=GPIOG,\n    .pin=GPIO13,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led0\"\n};\nstatic const struct gpio_config Led1 = {\n    .base=GPIOG,\n    .pin=GPIO14,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led1\"\n};\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_1\n    {\n        .devidx = 1,\n        .base = USART1,\n        .irq = NVIC_USART1_IRQ,\n        .rcc = RCC_USART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = USART2,\n        .irq = NVIC_USART2_IRQ,\n        .rcc = RCC_USART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO2,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO3,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\nstatic const struct i2c_config i2c_configs[] = {\n#ifdef CONFIG_I2C3\n    {\n        .idx  = 3,\n        .base = I2C3,\n        .ev_irq = NVIC_I2C3_EV_IRQ,\n        .er_irq = NVIC_I2C3_ER_IRQ,\n        .rcc = RCC_I2C3,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM4,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C3),\n            .irq = NVIC_DMA1_STREAM4_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C3),\n            .irq = NVIC_DMA1_STREAM2_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOA,\n            .pin=GPIO8,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown=GPIO_PUPD_PULLUP\n        },\n        .pio_sda = {\n            .base=GPIOC,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown=GPIO_PUPD_PULLUP\n        },\n    },\n#endif\n};\n#define NUM_I2CS (sizeof(i2c_configs) / sizeof(struct i2c_config))\n\nstatic const struct spi_config spi_configs[] = {\n#ifdef CONFIG_SPI_5\n    {\n        .idx  = 1,\n        .base = SPI5,\n        .irq = NVIC_SPI5_IRQ,\n        .rcc = RCC_SPI5,\n        .baudrate = 0, /* TODO: SPI baudrate */\n        .polarity = 1,\n        .phase = 1,\n        .rx_only = 0,\n        .bidir_mode = 0,\n        .dff_16 = 0,\n        .enable_software_slave_management = 1,\n        .send_msb_first = 1,\n\n        .tx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM4,\n            .channel = DMA_SxCR_CHSEL_2,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &SPI_DR(SPI5),\n            .irq = 0,\n        },\n        .rx_dma = {\n            .base = DMA2,\n            .stream = DMA_STREAM3,\n            .channel = DMA_SxCR_CHSEL_2,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &SPI_DR(SPI5),\n            .irq = NVIC_DMA2_STREAM3_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_sck = {\n            .base=GPIOF,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n        .pio_mosi = {\n            .base=GPIOF,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF5,\n            .optype=GPIO_OTYPE_PP,\n            .speed=GPIO_OSPEED_100MHZ,\n        },\n    },\n#endif\n};\n#define NUM_SPIS (sizeof(spi_configs) / sizeof(struct spi_config))\n\n#ifdef CONFIG_DEVSTMPE811\nstatic const struct ts_config ts_conf = {\n    {\n        .base=GPIOA,\n        .pin=GPIO15,\n        .mode=GPIO_MODE_INPUT,\n        .pullupdown=GPIO_PUPD_NONE,\n        .af=GPIO_AF15,\n    },\n    .bus=3,\n};\n#endif\n\nint machine_init(void)\n{\n    int i;\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[STM32_CLOCK]);\n    gpio_create(NULL, &Led0);\n    gpio_create(NULL, &Led1);\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n\n    /* I2Cs */\n    for (i = 0; i < NUM_I2CS; i++) {\n        i2c_create(&i2c_configs[i]);\n    }\n\n    /* SPIs */\n    for (i = 0; i < NUM_SPIS; i++) {\n        devspi_create(&spi_configs[i]);\n    }\n\n\n#ifdef CONFIG_DEVSTMPE811\n    stmpe811_init(&ts_conf);\n#endif\n\n    rng_create(1, RCC_RNG);\n    return 0;\n}\n"
  },
  {
    "path": "kernel/stm32f4/stm32f446nucleo.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include \"unicore-mx/stm32/usart.h\"\n#include \"unicore-mx/cm3/nvic.h\"\n#include \"drivers/stm32_sdio.h\"\n\n#ifdef CONFIG_DEVUART\n#include \"uart.h\"\n#endif\n\n#include \"dsp.h\"\n\n#include <unicore-mx/stm32/gpio.h>\n#include \"gpio.h\"\n#include \"rng.h\"\n\nstatic const struct gpio_addr gpio_addrs[] = {\n    {.base=GPIOD, .pin=GPIO12,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"gpio_3_12\"},\n    {.base=GPIOD, .pin=GPIO13,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"gpio_3_13\"},\n    {.base=GPIOD, .pin=GPIO14,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"gpio_3_14\"},\n    {.base=GPIOD, .pin=GPIO15,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"gpio_3_15\"},\n    {.base=GPIOA, .pin=GPIO0,.mode=GPIO_MODE_INPUT, .optype=GPIO_OTYPE_PP, .pullupdown=GPIO_PUPD_NONE, .name=\"gpio_0_0\"},\n#ifdef CONFIG_DEVUART\n#ifdef CONFIG_USART_1\n    {.base=GPIOA, .pin=GPIO9,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n    {.base=GPIOA, .pin=GPIO10,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=NULL,},\n#endif\n#ifdef CONFIG_USART_2\n    {.base=GPIOA, .pin=GPIO2,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n    {.base=GPIOA, .pin=GPIO3,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=NULL,},\n#endif\n#ifdef CONFIG_USART_3\n    {.base=GPIOD, .pin=GPIO8,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n    {.base=GPIOD, .pin=GPIO9,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=NULL,},\n#endif\n#ifdef CONFIG_USART_6\n    {.base=GPIOC, .pin=GPIO6,.mode=GPIO_MODE_AF,.af=GPIO_AF8, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n    {.base=GPIOC, .pin=GPIO7,.mode=GPIO_MODE_AF,.af=GPIO_AF8, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=NULL,},\n#endif\n#endif\n#ifdef CONFIG_STM32F4USB\n    {.base=GPIOA, .pin=GPIO9,.mode=GPIO_MODE_AF,.af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n    {.base=GPIOA, .pin=GPIO11,.mode=GPIO_MODE_AF,.af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n    {.base=GPIOA, .pin=GPIO12,.mode=GPIO_MODE_AF,.af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n#endif\n#ifdef CONFIG_DEVSTMETH\n    {.base=GPIOA, .pin=GPIO2, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11, .name=NULL}, // MDIO\n    {.base=GPIOC, .pin=GPIO1, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11, .name=NULL}, // MDC\n    {.base=GPIOA, .pin=GPIO1, .mode=GPIO_MODE_AF, .af=GPIO_AF11, .name=NULL},                        // RMII REF CLK\n    {.base=GPIOA, .pin=GPIO7, .mode=GPIO_MODE_AF, .af=GPIO_AF11, .name=NULL},                        // RMII CRS DV\n    {.base=GPIOB, .pin=GPIO10,.mode=GPIO_MODE_AF, .af=GPIO_AF11, .name=NULL},                        // RMII RXER\n    {.base=GPIOC, .pin=GPIO4, .mode=GPIO_MODE_AF, .af=GPIO_AF11, .name=NULL},                        // RMII RXD0\n    {.base=GPIOC, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF11, .name=NULL},                        // RMII RXD1\n    {.base=GPIOB, .pin=GPIO11,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11, .name=NULL}, // RMII TXEN\n    {.base=GPIOB, .pin=GPIO12,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11, .name=NULL}, // RMII TXD0\n    {.base=GPIOB, .pin=GPIO13,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11, .name=NULL}, // RMII TXD1\n    {.base=GPIOE, .pin=GPIO2, .mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=NULL, .pullupdown=GPIO_PUPD_PULLUP},            // PHY RESET\n#endif\n};\n#define NUM_GPIOS (sizeof(gpio_addrs) / sizeof(struct gpio_addr))\n\n#ifdef CONFIG_DEVUART\n     static const struct uart_addr uart_addrs[] = {\n#ifdef CONFIG_USART_1\n             {   .devidx = 1,\n                 .base = USART1,\n                 .irq = NVIC_USART1_IRQ,\n                 .rcc = RCC_USART1,\n                 .baudrate = 115200,\n                 .stop_bits = USART_STOPBITS_1,\n                 .data_bits = 8,\n                 .parity = USART_PARITY_NONE,\n                 .flow = USART_FLOWCONTROL_NONE,\n             },\n#endif\n#ifdef CONFIG_USART_2\n             {\n                 .devidx = 2,\n                 .base = USART2,\n                 .irq = NVIC_USART2_IRQ,\n                 .rcc = RCC_USART2,\n                 .baudrate = 115200,\n                 .stop_bits = USART_STOPBITS_1,\n                 .data_bits = 8,\n                 .parity = USART_PARITY_NONE,\n                 .flow = USART_FLOWCONTROL_NONE,\n             },\n#endif\n#ifdef CONFIG_USART_3\n             {\n                 .devidx = 3,\n                 .base = USART3,\n                 .irq = NVIC_USART3_IRQ,\n                 .rcc = RCC_USART3,\n                 .baudrate = 115200,\n                 .stop_bits = USART_STOPBITS_1,\n                 .data_bits = 8,\n                 .parity = USART_PARITY_NONE,\n                 .flow = USART_FLOWCONTROL_NONE,\n             },\n#endif\n#ifdef CONFIG_USART_6\n             {\n                 .devidx = 6,\n                 .base = USART6,\n                 .irq = NVIC_USART6_IRQ,\n                 .rcc = RCC_USART6,\n                 .baudrate = 115200,\n                 .stop_bits = USART_STOPBITS_1,\n                 .data_bits = 8,\n                 .parity = USART_PARITY_NONE,\n                 .flow = USART_FLOWCONTROL_NONE,\n             },\n#endif\n     };\n#define NUM_UARTS (sizeof(uart_addrs) / sizeof(struct uart_addr))\n#endif\n\n#ifdef CONFIG_RNG\n#include \"stm32_rng.h\"\nstatic const struct rng_addr rng_addrs[] = {\n            {\n                .devidx = 1,\n                .base = 1,\n                .rcc = RCC_RNG,\n            },\n};\n#define NUM_RNGS (sizeof(rng_addrs) / sizeof(struct rng_addr))\n#endif\n\n/* Setup GPIO Pins for SDIO:\n   PC8 - PC11 - DAT0 thru DAT3\n   PC12 - CLK\n   PD2 - CMD\n*/\nstruct sdio_config sdio_conf = {\n    .devidx = 0,\n    .base = SDIO_BASE,\n    .rcc_reg = (uint32_t *)&RCC_APB2ENR,\n    .rcc_en  = RCC_APB2ENR_SDIOEN,\n    .rcc_rst_reg = (uint32_t *)&RCC_APB2RSTR,\n    .rcc_rst  = RCC_APB2RSTR_SDIORST,\n    .card_detect_supported = 1,\n    .pio_dat0 = {\n        .base=GPIOC,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .af = GPIO_AF12,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n\n    },\n    .pio_dat1 = {\n        .base=GPIOC,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat2 = {\n        .base=GPIOC,\n        .pin=GPIO10,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat3 = {\n        .base=GPIOC,\n        .pin=GPIO11,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_clk = {\n        .base=GPIOC,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cmd = {\n        .base=GPIOD,\n        .pin=GPIO2,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cd = {\n        .base=GPIOB,\n        .pin=GPIO15,\n        .mode=GPIO_MODE_INPUT,\n        .pullupdown=GPIO_PUPD_PULLUP\n    }\n};\n\nvoid machine_init(struct fnode * dev)\n{\n#       if CONFIG_SYS_CLOCK == 48000000\n        rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_48MHZ]);\n#       elif CONFIG_SYS_CLOCK == 84000000\n        rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_84MHZ]);\n#       elif CONFIG_SYS_CLOCK == 120000000\n        rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_120MHZ]);\n#       elif CONFIG_SYS_CLOCK == 168000000\n        rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);\n#       elif CONFIG_SYS_CLOCK == 180000000\n        rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_180MHZ]);\n#       else\n#error No valid clock speed selected\n#endif\n\n    gpio_init(dev, gpio_addrs, NUM_GPIOS);\n#ifdef CONFIG_DEVUART\n    uart_init(dev, uart_addrs, NUM_UARTS);\n#endif\n    rng_init(dev, rng_addrs, NUM_RNGS);\n    sdio_init(&sdio_conf);\n#ifdef CONFIG_DSP\n    dsp_init(dev);\n#endif\n\n#ifdef CONFIG_DEVSTMETH\n    gpio_clear(GPIOE,GPIO2);    /* Clear ETH nRESET pin */\n    gpio_set(GPIOE,GPIO2);      /* Set ETH nRESET pin */\n#endif\n}\n"
  },
  {
    "path": "kernel/stm32f4/stm32f4x1discovery.c",
    "content": "/*  \n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as \n *      published by the Free Software Foundation.\n *      \n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */  \n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include \"unicore-mx/cm3/nvic.h\"\n#include <unicore-mx/stm32/dma.h>\n#include \"unicore-mx/stm32/usart.h\"\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/stm32/exti.h>\n#include <unicore-mx/stm32/spi.h>\n#include <unicore-mx/stm32/i2c.h>\n#include <unicore-mx/stm32/adc.h>\n\n#include \"uart.h\"\n#include \"gpio.h\"\n#include \"adc.h\"\n\n\n\n#if CONFIG_SYS_CLOCK == 48000000\n    static const uint32_t rcc_clock = RCC_CLOCK_3V3_48MHZ;\n#elif CONFIG_SYS_CLOCK == 84000000\n    static const uint32_t rcc_clock = RCC_CLOCK_3V3_84MHZ;\n#else\n#   error No valid clock speed selected for STM32F4x1 Discovery\n#endif\n\nstatic const struct gpio_config Leds[] = { \n            {.base=GPIOD, .pin=GPIO12,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"led0\"},\n            {.base=GPIOD, .pin=GPIO13,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"led1\"},\n            {.base=GPIOD, .pin=GPIO14,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"led2\"},\n            {.base=GPIOD, .pin=GPIO15,.mode=GPIO_MODE_OUTPUT, .optype=GPIO_OTYPE_PP, .name=\"led3\"},\n};\nstatic const struct gpio_config Button = {.base=GPIOA, .pin=GPIO0,.mode=GPIO_MODE_INPUT, .pullupdown=GPIO_PUPD_NONE, .name=NULL};\n\n\n#ifdef CONFIG_DEVUART\nstatic const struct uart_config uart_configs[] = { \n#ifdef CONFIG_USART_1\n        {   .devidx = 1,\n            .base = USART1, \n            .irq = NVIC_USART1_IRQ, \n            .rcc = RCC_USART1, \n            .baudrate = 115200,\n            .stop_bits = USART_STOPBITS_1,\n            .data_bits = 8,\n            .parity = USART_PARITY_NONE,\n            .flow = USART_FLOWCONTROL_NONE,\n            .pio_rx = {.base=GPIOA, .pin=GPIO9,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n            .pio_tx = {.base=GPIOA, .pin=GPIO10,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=NULL,},\n        },\n#endif\n#ifdef CONFIG_USART_2\n        { \n            .devidx = 2,\n            .base = USART2, \n            .irq = NVIC_USART2_IRQ, \n            .rcc = RCC_USART2, \n            .baudrate = 115200,\n            .stop_bits = USART_STOPBITS_1,\n            .data_bits = 8,\n            .parity = USART_PARITY_NONE,\n            .flow = USART_FLOWCONTROL_NONE,\n            .pio_rx = {.base=GPIOA, .pin=GPIO2,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n            .pio_tx = {.base=GPIOA, .pin=GPIO3,.mode=GPIO_MODE_AF,.af=GPIO_AF7, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=NULL,},\n        },\n#endif\n#ifdef CONFIG_USART_6\n        { \n            .devidx = 6,\n            .base = USART6, \n            .irq = NVIC_USART6_IRQ, \n            .rcc = RCC_USART6, \n            .baudrate = 115200,\n            .stop_bits = USART_STOPBITS_1,\n            .data_bits = 8,\n            .parity = USART_PARITY_NONE,\n            .flow = USART_FLOWCONTROL_NONE,\n            .pio_rx = {.base=GPIOC, .pin=GPIO6,.mode=GPIO_MODE_AF,.af=GPIO_AF8, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n            .pio_tx = {.base=GPIOC, .pin=GPIO7,.mode=GPIO_MODE_AF,.af=GPIO_AF8, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=NULL,},\n        },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n#endif\n\n\n\n/* TODO */\n#if 0 \n\n#ifdef CONFIG_DEVI2C\n#ifdef CONFIG_I2C_1\n            {.base=GPIOB, .pin=GPIO6,.mode=GPIO_MODE_AF,.af=GPIO_AF4, .speed=GPIO_OSPEED_50MHZ, .optype=GPIO_OTYPE_OD, .pullupdown=GPIO_PUPD_PULLUP, .name=NULL,},\n            {.base=GPIOB, .pin=GPIO9,.mode=GPIO_MODE_AF,.af=GPIO_AF4, .speed=GPIO_OSPEED_50MHZ, .optype=GPIO_OTYPE_OD, .pullupdown=GPIO_PUPD_PULLUP, .name=NULL,},\n#ifdef CONFIG_DEVLSM303DLHC\n            /* Depends on I2C_1 : DRDY - PE2 Int1 - E4 Int2 - E5 */\n            {.base=GPIOE, .pin=GPIO2,.mode=GPIO_MODE_INPUT, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n            {.base=GPIOE, .pin=GPIO4,.mode=GPIO_MODE_INPUT, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n            {.base=GPIOE, .pin=GPIO5,.mode=GPIO_MODE_INPUT, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n#endif\n#endif\n#endif\n\n#ifdef CONFIG_DEVSPI\n#ifdef CONFIG_SPI_1\n            /* SCK - PA5 MISO - PA6 MOSI - */\n            {.base=GPIOA, .pin=GPIO5,.mode=GPIO_MODE_AF,.af=GPIO_AF5, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n            {.base=GPIOA, .pin=GPIO6,.mode=GPIO_MODE_AF,.af=GPIO_AF5, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n            {.base=GPIOA, .pin=GPIO7,.mode=GPIO_MODE_AF,.af=GPIO_AF5, .pullupdown=GPIO_PUPD_NONE, .name=NULL,},\n#ifdef CONFIG_DEVL3GD20\n            /* Depends on SPI_1 :  CS - PE3 INT1 - PE0 INT2 - PE1 */\n            {.base=GPIOE, .pin=GPIO3,.mode=GPIO_MODE_OUTPUT, .speed=GPIO_OSPEED_25MHZ, .optype=GPIO_OTYPE_PP, .name=\"l3gd20_cs\"},\n            {.base=GPIOE, .pin=GPIO0,.mode=GPIO_MODE_INPUT, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n            {.base=GPIOE, .pin=GPIO1,.mode=GPIO_MODE_INPUT, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n#endif\n#endif\n#endif\n\n#ifdef CONFIG_DEVADC\n            {.base=GPIOA, .pin=GPIO1,.mode=GPIO_MODE_ANALOG, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n            {.base=GPIOB, .pin=GPIO0,.mode=GPIO_MODE_ANALOG, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n            {.base=GPIOB, .pin=GPIO1,.mode=GPIO_MODE_ANALOG, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n#endif\n\n#ifdef CONFIG_STM32F4USB\n            {.base=GPIOA, .pin=GPIO9,.mode=GPIO_MODE_AF,.af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n            {.base=GPIOA, .pin=GPIO11,.mode=GPIO_MODE_AF,.af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n            {.base=GPIOA, .pin=GPIO12,.mode=GPIO_MODE_AF,.af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .name=NULL},\n#endif\n\n};\n\n\n\n#ifdef CONFIG_DEVSPI\nstatic const struct spi_addr spi_addrs[] = { \n#ifdef CONFIG_SPI_1\n        {\n            .base = SPI1, \n            .irq = NVIC_SPI1_IRQ, \n            .rcc = RCC_SPI1,\n\n            /* Move this to the upper driver */\n            .baudrate_prescaler = SPI_CR1_BR_FPCLK_DIV_256,\n            .clock_pol = 1,\n            .clock_phase = 1,\n            .rx_only = 0,\n            .bidir_mode = 0,\n            .dff_16 = 0,\n            .enable_software_slave_management = 1,\n            .send_msb_first = 1,\n            /* End move */\n            \n            .name = \"spi1\",\n            .tx_dma = {\n                .base = DMA2,\n                .stream = DMA_STREAM3,\n                .channel = DMA_SxCR_CHSEL_3,\n                .psize =  DMA_SxCR_PSIZE_8BIT,\n                .msize = DMA_SxCR_MSIZE_8BIT,\n                .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n                .prio = DMA_SxCR_PL_MEDIUM,\n                .paddr =  (uint32_t) &SPI_DR(SPI1),\n                .irq = 0,\n            },\n            .rx_dma = {\n                .base = DMA2,\n                .stream = DMA_STREAM2,\n                .channel = DMA_SxCR_CHSEL_3,\n                .psize =  DMA_SxCR_PSIZE_8BIT,\n                .msize = DMA_SxCR_MSIZE_8BIT,\n                .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n                .prio = DMA_SxCR_PL_VERY_HIGH,\n                .paddr =  (uint32_t) &SPI_DR(SPI1),\n                .irq = NVIC_DMA2_STREAM2_IRQ,\n            },\n           \n            .dma_rcc = RCC_DMA2,\n            \n        },\n#endif\n};\n#define NUM_SPIS (sizeof(spi_addrs) / sizeof(struct spi_addr))\n#endif\n\n\n#ifdef CONFIG_DEVI2C\nstatic const struct i2c_addr i2c_addrs[] = { \n#ifdef CONFIG_I2C_1\n        {\n            .base = I2C1,\n            .ev_irq = NVIC_I2C1_EV_IRQ,\n            .er_irq = NVIC_I2C1_ER_IRQ,\n            .rcc = RCC_I2C1,\n            \n            .clock_f = I2C_CR2_FREQ_36MHZ,\n            .fast_mode = 1,\n            .rise_time = 11,\n            .bus_clk_frequency = 10,\n\n            .name = \"i2c1\",\n            .tx_dma = {\n                .base = DMA1,\n                .stream = DMA_STREAM6,\n                .channel = DMA_SxCR_CHSEL_1,\n                .psize =  DMA_SxCR_PSIZE_8BIT,\n                .msize = DMA_SxCR_MSIZE_8BIT,\n                .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n                .prio = DMA_SxCR_PL_MEDIUM,\n                .paddr =  (uint32_t) &I2C_DR(I2C1),\n                .irq = NVIC_DMA1_STREAM6_IRQ,\n            },\n            .rx_dma = {\n                .base = DMA1,\n                .stream = DMA_STREAM0,\n                .channel = DMA_SxCR_CHSEL_1,\n                .psize =  DMA_SxCR_PSIZE_8BIT,\n                .msize = DMA_SxCR_MSIZE_8BIT,\n                .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n                .prio = DMA_SxCR_PL_VERY_HIGH,\n                .paddr =  (uint32_t) &I2C_DR(I2C1),\n                .irq = NVIC_DMA1_STREAM0_IRQ,\n            },\n                    \n            .dma_rcc = RCC_DMA1,\n        },\n#endif\n};\n#define NUM_I2CS (sizeof(i2c_addrs) / sizeof(struct i2c_addr))\n#endif\n\n\n#ifdef CONFIG_DEVADC\nstatic const struct adc_config adc_configs[] = { \n        {\n            .base = ADC1, \n            .irq = NVIC_ADC_IRQ, \n            .rcc = RCC_ADC1,\n            .name = \"adc\",\n            .channel_array = {1, 8, 9},     /*ADC_IN1,8,9 on PA1, PB0, PB1 */\n            .num_channels = 3,\n            /* Use DMA to fetch sample data */\n            .dma = {\n                .base = DMA2,\n                .stream = DMA_STREAM0,\n                .channel = DMA_SxCR_CHSEL_1,\n                .psize =  DMA_SxCR_PSIZE_16BIT,\n                .msize = DMA_SxCR_MSIZE_16BIT,\n                .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n                .prio = DMA_SxCR_PL_HIGH,\n                .paddr =  (uint32_t) &ADC_DR(ADC1),\n                .irq = NVIC_DMA2_STREAM0_IRQ,\n            },\n            .dma_rcc = RCC_DMA2,\n        }\n};\n#define NUM_ADC (sizeof(adc_configs)/sizeof(struct adc_config))\n#endif\n\n#ifdef CONFIG_DEVLSM303DLHC\n#include \"drivers/lsm303dlhc.h\"\nstatic const struct lsm303dlhc_addr lsm303dlhc_addr = {\n    .name = \"l3gd20\",\n    .i2c_name = \"/dev/i2c1\",\n    .pio1_base = GPIOE,\n    .pio2_base = GPIOE,\n    .drdy_base = GPIOE,\n    .pio1_pin = GPIO4,\n    .pio2_pin = GPIO5,\n    .drdy_pin = GPIO2,\n    .address = 0x32,\n    .drdy_address = 0x3C\n};\n#endif\n#ifdef CONFIG_DEVL3GD20\n#include \"drivers/l3gd20.h\"\nstatic const struct l3gd20_addr l3gd20_addr = {\n    .name = \"l3gd20\",\n    .spi_name = \"/dev/spi1\",\n    .spi_cs_name = \"/dev/l3gd20_cs\",\n    .pio1_base = GPIOE,\n    .pio2_base = GPIOE,\n    .pio1_pin = GPIO0,\n    .pio2_pin = GPIO1,\n};\n#endif\n\n#endif \n\nint machine_init(void)\n{\n    int i;\n    /* Clock */\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[rcc_clock]);\n\n    /* Button */\n    gpio_create(NULL, &Button);\n\n    /* Leds */\n    for (i = 0; i < 4; i++) {\n        gpio_create(NULL, &Leds[i]);\n    }\n\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n    return 0;\n\n    /* TODO: port to new pinmux */\n#if 0\n#ifdef CONFIG_DEVSPI\n    spi_init(dev, spi_addrs, NUM_SPIS);\n#ifdef CONFIG_DEVL3GD20\n    l3gd20_init(dev, l3gd20_addrs, NUM_L3GD20);\n#endif\n#endif\n#ifdef CONFIG_DEVI2C\n    i2c_init(dev, i2c_addrs, NUM_I2CS);\n#ifdef CONFIG_DEVLSM303DLHC\n    lsm303dlhc_init(dev, lsm303dlhc_addrs, NUM_LSM303DLHC);\n#endif\n#endif\n\n#ifdef CONFIG_DEVADC\n    adc_init(adc_configs, NUM_ADC);\n#endif\n\n#ifdef CONFIG_DEVLSM303DLHC\n    lsm303dlhc_init(dev, lsm303dlhc_addr);\n#endif\n\n#ifdef CONFIG_DEVL3GD20\n    l3gd20_init(dev, l3gd20_addr);\n#endif\n#endif \n\n}\n\n"
  },
  {
    "path": "kernel/stm32f4/stm32f4xxpyboard.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include <unicore-mx/cm3/systick.h>\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/usart.h>\n#include <unicore-mx/stm32/gpio.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/sdio.h>\n#include <unicore-mx/stm32/i2c.h>\n#include <unicore-mx/stm32/dma.h>\n#include \"unicore-mx/stm32/spi.h\"\n#include \"drivers/stm32_sdio.h\"\n\n#include \"uart.h\"\n#include \"gpio.h\"\n#include \"sdio.h\"\n#include \"dsp.h\"\n#include \"rng.h\"\n#include \"usb.h\"\n#include \"i2c.h\"\n#include \"dma.h\"\n#include \"drivers/lis3dsh.h\"\n\nextern int xadow_led_init(uint32_t bus);\n\n#if CONFIG_SYS_CLOCK == 48000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_48MHZ\n#elif CONFIG_SYS_CLOCK == 84000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_84MHZ\n#elif CONFIG_SYS_CLOCK == 100000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_100MHZ\n#elif CONFIG_SYS_CLOCK == 120000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_120MHZ\n#elif CONFIG_SYS_CLOCK == 168000000\n#    define STM32_CLOCK RCC_CLOCK_3V3_168MHZ\n#else\n#   error No valid clock speed selected\n#endif\n\nstatic const struct gpio_config Led[4] = {\n    {\n        .base=GPIOA,\n        .pin=GPIO13,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led0\"\n    },\n    {\n        .base=GPIOA,\n        .pin=GPIO14,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led1\"\n    },\n    {\n        .base=GPIOA,\n        .pin=GPIO15,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led2\"\n    },\n    {\n        .base=GPIOB,\n        .pin=GPIO4,.mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n        .name=\"led3\"\n    },\n};\n\nstatic const struct gpio_config Button = {\n    .base=GPIOB,\n    .pin=GPIO3,\n    .mode=GPIO_MODE_INPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_NONE,\n    .name=\"button\"\n};\n\nstatic struct usb_pio_config_fs pio_fs = {\n    .pio_vbus = {\n        .base=GPIOA,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dm =   {\n        .base=GPIOA,\n        .pin=GPIO11,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dp =   {\n        .base=GPIOA,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    }\n};\n\nstatic struct usb_config usb_guest = {\n    .dev_type = USB_DEV_FS,\n    .otg_mode = USB_MODE_GUEST,\n    .pio.fs = &pio_fs\n};\n\n\nstatic const struct i2c_config i2c_configs[] = {\n#ifdef CONFIG_I2C1\n    {\n        .idx  = 1,\n        .base = I2C1,\n        .ev_irq = NVIC_I2C1_EV_IRQ,\n        .er_irq = NVIC_I2C1_ER_IRQ,\n        .rcc = RCC_I2C1,\n        .dma_rcc = RCC_DMA2,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM6,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM6_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM0,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM0_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOB,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n        .pio_sda = {\n            .base=GPIOB,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_I2C2\n    {\n        .idx  = 1,\n        .base = I2C2,\n        .ev_irq = NVIC_I2C2_EV_IRQ,\n        .er_irq = NVIC_I2C2_ER_IRQ,\n        .rcc = RCC_I2C2,\n        .dma_rcc = RCC_DMA1,\n\n        .clock_f = I2C_CR2_FREQ_36MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM7,\n            .channel = DMA_SxCR_CHSEL_7,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C2),\n            .irq = NVIC_DMA1_STREAM7_IRQ,\n        },\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_7,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C2),\n            .irq = NVIC_DMA1_STREAM7_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOB,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n        .pio_sda = {\n            .base=GPIOB,\n            .pin=GPIO11,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown = GPIO_PUPD_NONE\n        },\n    },\n#endif\n};\n#define NUM_I2CS (sizeof(i2c_configs) / sizeof(struct i2c_config))\n\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_USART_1\n    {   .devidx = 1,\n        .base = USART1,\n        .irq = NVIC_USART1_IRQ,\n        .rcc = RCC_USART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOB,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOB,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = USART2,\n        .irq = NVIC_USART2_IRQ,\n        .rcc = RCC_USART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO3,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO2,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_3\n    {\n        .devidx = 3,\n        .base = USART3,\n        .irq = NVIC_USART3_IRQ,\n        .rcc = RCC_USART3,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {\n            .base=GPIOB,\n            .pin=GPIO11,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n        .pio_tx = {\n            .base=GPIOB,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_4\n    {\n        .devidx = 4,\n        .base = USART4,\n        .irq = NVIC_USART4_IRQ,\n        .rcc = RCC_USART4,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO1,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO0,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n#ifdef CONFIG_USART_6\n    {\n        .devidx = 6,\n        .base = USART6,\n        .irq = NVIC_USART6_IRQ,\n        .rcc = RCC_USART6,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n\n        .pio_rx = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .pullupdown=GPIO_PUPD_NONE,\n        },\n        .pio_tx = {\n            .base=GPIOC,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n    },\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\n/* Setup GPIO Pins for SDIO:\n   PC8 - PC11 - DAT0 thru DAT3\n   PC12 - CLK\n   PD2 - CMD\n*/\nstruct sdio_config sdio_conf = {\n    .devidx = 0,\n    .base = SDIO_BASE,\n    .rcc_reg = (uint32_t *)&RCC_APB2ENR,\n    .rcc_en  = RCC_APB2ENR_SDIOEN,\n    .rcc_rst_reg = (uint32_t *)&RCC_APB2RSTR,\n    .rcc_rst  = RCC_APB2RSTR_SDIORST,\n    .card_detect_supported = 1,\n    .pio_dat0 = {\n        .base=GPIOC,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .af = GPIO_AF12,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n\n    },\n    .pio_dat1 = {\n        .base=GPIOC,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat2 = {\n        .base=GPIOC,\n        .pin=GPIO10,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat3 = {\n        .base=GPIOC,\n        .pin=GPIO11,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_clk = {\n        .base=GPIOC,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cmd = {\n        .base=GPIOD,\n        .pin=GPIO2,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cd = {\n        .base=GPIOA,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_INPUT,\n        .pullupdown=GPIO_PUPD_PULLUP\n    }\n};\n\nint machine_init(void)\n{\n    int i;\n    /* Clock */\n\n#ifdef CLOCK_12MHZ\n    rcc_clock_setup_hse_3v3(&rcc_hse_12mhz_3v3[STM32_CLOCK]);\n#else\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[STM32_CLOCK]);\n#endif\n\n    /* Leds */\n    for (i = 0; i < 4; i++) {\n        gpio_create(NULL, &Led[i]);\n    }\n\n    /* Button */\n    gpio_create(NULL, &Button);\n\n    /* Uarts */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n\n    /* I2Cs */\n    for (i = 0; i < NUM_I2CS; i++) {\n        i2c_create(&i2c_configs[i]);\n    }\n\n\n    rng_create(1, RCC_RNG);\n    sdio_init(&sdio_conf);\n    usb_init(&usb_guest);\n    #ifdef CONFIG_DEVMCCOG21\n    mccog21_init(1);\n    #endif\n    #ifdef CONFIG_DEVXALED5X7\n    xadow_led_init(1);\n    #endif\n    return 0;\n}\n"
  },
  {
    "path": "kernel/stm32f7/Kconfig",
    "content": "if ARCH_STM32F7\n\nchoice \n    prompt \"MCU\"\n    default ARCH_STM32F746_NG\n\nconfig ARCH_STM32F746_NG\n    bool \"STM32F746NG 1MB\"\n    select FLASH_SIZE_1MB\n    select RAM_SIZE_320KB\n    select ARCH_STM32F746\n\nconfig ARCH_STM32F769_NI\n    bool \"STM32F769NI 2MB\"\n    select FLASH_SIZE_2MB\n    select RAM_SIZE_368KB\n    select ARCH_STM32F769\n\nendchoice\n\nendif\n"
  },
  {
    "path": "kernel/stm32f7/stm32f7.ld.in",
    "content": "MEMORY\n{\n    FLASH (rx) : ORIGIN = __FLASH_ORIGIN, LENGTH = __KFLASHMEM_SIZE\n    SRAM (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __KRAMMEM_SIZE\n    SRAM_USER (rwx) : ORIGIN = (__RAM1_BASE + __KRAMMEM_SIZE), LENGTH = (__RAM1_SIZE - __KRAMMEM_SIZE)\n    SDRAM_USER(rwx) : ORIGIN = __SDRAM_BASE, LENGTH = __SDRAM_SIZE\n}\n\n /* Enforce emmition of the vector table. */\nEXTERN (vector_table)\n\n/* Define the entry point of the output file. */\nENTRY(reset_handler)\n\nSECTIONS\n{\n    .text :\n    {\n        KEEP(*(.vectors))\n        *(.text*)\n        *(.rodata*)\n    } > FLASH\n\t/* C++ Static constructors/destructors, also used for __attribute__\n\t * ((constructor)) and the likes */\n\t.preinit_array : {\n\t\t. = ALIGN(4);\n\t\t__preinit_array_start = .;\n\t\tKEEP (*(.preinit_array))\n\t\t__preinit_array_end = .;\n\t} > FLASH\n\t.init_array : {\n\t\t. = ALIGN(4);\n\t\t__init_array_start = .;\n\t\tKEEP (*(SORT(.init_array.*)))\n\t\tKEEP (*(.init_array))\n\t\t__init_array_end = .;\n\t} > FLASH\n\t.fini_array : {\n\t\t. = ALIGN(4);\n\t\t__fini_array_start = .;\n\t\tKEEP (*(.fini_array))\n\t\tKEEP (*(SORT(.fini_array.*)))\n\t\t__fini_array_end = .;\n\t} > FLASH\n \n    .data :\n    {\n        _etext = LOADADDR(.data);\n        _data = .;\n        *(vtable)\n        *(.data*)\n        _edata = .;\n    } > SRAM AT > FLASH\n\t_data_loadaddr = LOADADDR(.data);\n \n    .bss :\n    {\n        _bss = .;\n        *(.bss*)\n        *(COMMON)\n        . = ALIGN(32 / 8);\n        _ebss = .;\n        PROVIDE (end = .);\n    } > SRAM\n\n    .heap :\n    {\n        /* heap starts after BSS */\n        PROVIDE(_heap_start = _ebss );\n    } > SRAM\n}\n\nPROVIDE(_stack = ORIGIN(SRAM) + LENGTH(SRAM));\nPROVIDE(_user_heap_start = ORIGIN(SRAM_USER));\nPROVIDE(_user_heap_end = ORIGIN(SRAM_USER) + LENGTH(SRAM_USER));\nPROVIDE(_external_heap_start = ORIGIN(SDRAM_USER));\nPROVIDE(_external_heap_end = ORIGIN(SDRAM_USER) + LENGTH(SDRAM_USER));\nPROVIDE(_extra_heap_start = ORIGIN(SDRAM_USER));\nPROVIDE(_extra_heap_end = ORIGIN(SDRAM_USER) + LENGTH(SDRAM_USER));\n\n"
  },
  {
    "path": "kernel/stm32f7/stm32f746discovery.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/usart.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/f7/usart.h>\n#include <unicore-mx/stm32/i2c.h>\n#include <unicore-mx/stm32/dma.h>\n\n#if CONFIG_SYS_CLOCK == 216000000\n#else\n#error No valid clock speed selected for STM32F729 Discovery\n#endif\n\n#include \"gpio.h\"\n#include \"uart.h\"\n#include \"rng.h\"\n#include \"sdram.h\"\n#include \"sdio.h\"\n#include \"framebuffer.h\"\n#include \"ltdc.h\"\n#include \"usb.h\"\n#include \"eth.h\"\n#include \"i2c.h\"\n#include \"tty_console.h\"\n\nstatic const struct gpio_config gpio_led0 = {\n    .base=GPIOI,\n    .pin=GPIO1,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led0\"\n};\n\nstatic const struct gpio_config gpio_button = {\n    .base=GPIOI,\n    .pin=GPIO11,\n    .mode=GPIO_MODE_INPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_PULLUP,\n    .name=\"button\"\n};\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_DEVUART\n#ifdef CONFIG_USART_1\n    {\n        .devidx = 1,\n        .base = USART1,\n        .irq = NVIC_USART1_IRQ,\n        .rcc = RCC_USART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOB,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_USART_6\n    {\n        .devidx = 6,\n        .base = USART6,\n        .irq = NVIC_USART6_IRQ,\n        .rcc = RCC_USART6,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOC,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\n\n/* Setup GPIO Pins for SDIO:\n   PC8 - PC11 - DAT0 thru DAT3\n   PC12 - CLK\n   PD2 - CMD\n*/\nstruct sdio_config sdio_conf = {\n    .devidx = 0,\n    .base = (uint32_t *)SDIO_BASE,\n    .rcc_reg = (uint32_t *)&RCC_APB2ENR,\n    .rcc_en  = RCC_APB2ENR_SDMMC1EN,\n    .rcc_rst_reg = (uint32_t *)&RCC_APB2RSTR,\n    .rcc_rst  = RCC_APB2RSTR_SDMMC1RST,\n    .card_detect_supported = 1,\n    .pio_dat0 = {\n        .base=GPIOC,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .af = GPIO_AF12,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n\n    },\n    .pio_dat1 = {\n        .base=GPIOC,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat2 = {\n        .base=GPIOC,\n        .pin=GPIO10,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat3 = {\n        .base=GPIOC,\n        .pin=GPIO11,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_clk = {\n        .base=GPIOC,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cmd = {\n        .base=GPIOD,\n        .pin=GPIO2,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cd = {\n        .base=GPIOC,\n        .pin=GPIO13,\n        .mode=GPIO_MODE_INPUT,\n        .pullupdown=GPIO_PUPD_PULLUP\n    }\n};\n\nstruct gpio_config stm32eth_mii_pins[] = {\n    {.base=GPIOA, .pin=GPIO1, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII REF CLK\n    {.base=GPIOA, .pin=GPIO2, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDIO\n    {.base=GPIOA, .pin=GPIO7, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII CRS DV\n    {.base=GPIOG, .pin=GPIO2, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXER\n    {.base=GPIOG, .pin=GPIO11,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXEN\n    {.base=GPIOG, .pin=GPIO13,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD0\n    {.base=GPIOG, .pin=GPIO14,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD1\n    {.base=GPIOC, .pin=GPIO1, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDC\n    {.base=GPIOC, .pin=GPIO4, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD0\n    {.base=GPIOC, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD1\n};\n\nstatic struct eth_config eth_config = {\n    .pio_mii = stm32eth_mii_pins,\n    .n_pio_mii = sizeof(stm32eth_mii_pins)/sizeof(struct gpio_config),\n    .pio_phy_reset = {},\n    .has_phy_reset = 0\n};\n\nstatic struct usb_pio_config_fs pio_usbfs = {\n    .pio_vbus = {\n        .base=GPIOA,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dm =   {\n        .base=GPIOA,\n        .pin=GPIO11,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dp =   {\n        .base=GPIOA,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_phy = {\n        .base = GPIOD,\n        .pin = GPIO5,\n        .mode=GPIO_MODE_OUTPUT,\n        .pullupdown = GPIO_PUPD_NONE\n    }\n};\n\nstatic struct usb_pio_config_hs pio_usbhs = {\n    .ulpi_data = {\n        { .base=GPIOA, .pin=GPIO3, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE,  .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n        { .base=GPIOB, .pin=GPIO0, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE , .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n        { .base=GPIOB, .pin=GPIO1, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE , .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n        { .base=GPIOB, .pin=GPIO10, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n        { .base=GPIOB, .pin=GPIO11, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n        { .base=GPIOB, .pin=GPIO12, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n        { .base=GPIOB, .pin=GPIO13, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE, .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n        { .base=GPIOB, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .pullupdown=GPIO_PUPD_NONE , .optype=GPIO_OTYPE_PP, .speed=GPIO_OSPEED_100MHZ},\n    },\n    .ulpi_clk  = { .base=GPIOA, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .optype=GPIO_OTYPE_PP, .pullupdown=GPIO_PUPD_NONE, .speed=GPIO_OSPEED_100MHZ},\n    .ulpi_dir  = { .base=GPIOC, .pin=GPIO2, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .optype=GPIO_OTYPE_PP, .pullupdown=GPIO_PUPD_NONE, .speed=GPIO_OSPEED_100MHZ},\n    .ulpi_next = { .base=GPIOH, .pin=GPIO4, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .optype=GPIO_OTYPE_PP, .pullupdown=GPIO_PUPD_NONE, .speed=GPIO_OSPEED_100MHZ},\n    .ulpi_step = { .base=GPIOC, .pin=GPIO0, .mode=GPIO_MODE_AF, .af=GPIO_AF10, .optype=GPIO_OTYPE_PP, .pullupdown=GPIO_PUPD_NONE, .speed=GPIO_OSPEED_100MHZ}\n};\n\nstatic struct usb_config usb_fs_guest = {\n    .dev_type = USB_DEV_FS,\n    .otg_mode = USB_MODE_GUEST,\n    .pio.fs = &pio_usbfs\n};\n\nstatic struct usb_config usb_hs_guest = {\n    .dev_type = USB_DEV_HS,\n    .otg_mode = USB_MODE_GUEST,\n    .pio.hs = &pio_usbhs\n};\n\nstatic struct usb_config usb_hs_host = {\n    .dev_type = USB_DEV_HS,\n    .otg_mode = USB_MODE_HOST,\n    .pio.hs = &pio_usbhs\n};\n\n/** I2C:\n *    Touchscreen:\n *    INT = PI13\n *    CLK = PI14\n *    R0  = PI15\n *    SCL = PH7\n *    SDA = PH8\n *    VSYNC = PI10\n *    HSYNC = PI11\n *    Address = 01110000\n */\nstatic const struct i2c_config i2c_configs[] = {\n#ifdef CONFIG_I2C1\n    {\n        .idx  = 1,\n        .base = I2C1,\n        .ev_irq = NVIC_I2C1_EV_IRQ,\n        .er_irq = NVIC_I2C1_ER_IRQ,\n        .rcc = RCC_I2C1,\n\n        .clock_f = I2C_CR2_FREQ_42MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM0,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM0_IRQ,\n        },\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM6,\n            .channel = DMA_SxCR_CHSEL_1,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C1),\n            .irq = NVIC_DMA1_STREAM6_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOB,\n            .pin=GPIO8,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown=GPIO_PUPD_PULLUP\n        },\n        .pio_sda = {\n            .base=GPIOB,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown=GPIO_PUPD_PULLUP\n        },\n    },\n#endif\n#ifdef CONFIG_I2C3\n    {\n        .idx  = 3,\n        .base = I2C3,\n        .ev_irq = NVIC_I2C3_EV_IRQ,\n        .er_irq = NVIC_I2C3_ER_IRQ,\n        .rcc = RCC_I2C3,\n\n        .clock_f = I2C_CR2_FREQ_42MHZ,\n        .fast_mode = 1,\n        .rise_time = 11,\n        .bus_clk_frequency = 10,\n\n        .rx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM2,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_PERIPHERAL_TO_MEM,\n            .prio = DMA_SxCR_PL_VERY_HIGH,\n            .paddr =  (uint32_t) &I2C_DR(I2C3),\n            .irq = NVIC_DMA1_STREAM2_IRQ,\n        },\n        .tx_dma = {\n            .base = DMA1,\n            .stream = DMA_STREAM4,\n            .channel = DMA_SxCR_CHSEL_3,\n            .psize =  DMA_SxCR_PSIZE_8BIT,\n            .msize = DMA_SxCR_MSIZE_8BIT,\n            .dirn = DMA_SxCR_DIR_MEM_TO_PERIPHERAL,\n            .prio = DMA_SxCR_PL_MEDIUM,\n            .paddr =  (uint32_t) &I2C_DR(I2C3),\n            .irq = NVIC_DMA1_STREAM4_IRQ,\n        },\n        .dma_rcc = RCC_DMA1,\n        .pio_scl = {\n            .base=GPIOH,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown=GPIO_PUPD_PULLUP\n        },\n        .pio_sda = {\n            .base=GPIOH,\n            .pin=GPIO8,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF4,\n            .speed=GPIO_OSPEED_50MHZ,\n            .optype=GPIO_OTYPE_OD,\n            .pullupdown=GPIO_PUPD_PULLUP\n        },\n    },\n#endif\n};\n#define NUM_I2CS (sizeof(i2c_configs) / sizeof(struct i2c_config))\n\nextern int ft5336_init(uint32_t);\nextern int mccog21_init(uint32_t);\n\nint machine_init(void)\n{\n    int i = 0;\n    rcc_clock_setup_hse_3v3(&rcc_hse_25mhz_3v3);\n\n    usb_init(&usb_hs_host);\n\n    gpio_create(NULL, &gpio_led0);\n    gpio_create(NULL, &gpio_button);\n    /* UARTS */\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n    /* I2Cs */\n    for (i = 0; i < NUM_I2CS; i++) {\n        i2c_create(&i2c_configs[i]);\n    }\n    rng_create(1, RCC_RNG);\n    sdio_init(&sdio_conf);\n    /* Initialize USB OTG guest in full-speed mode */\n    //usb_init(&usb_fs_guest);\n\n\n    ethernet_init(&eth_config);\n\n\n    #ifdef CONFIG_DEVMCCOG21\n        mccog21_init(1);\n    #endif\n    #ifdef CONFIG_DEVFT5336\n       ft5336_init(3); /* FT5336 touch screen on I2C-3 */\n    #endif\n\n    return 0;\n}\n\n"
  },
  {
    "path": "kernel/stm32f7/stm32f746nucleo-144.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/usart.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/f7/usart.h>\n\n#if CONFIG_SYS_CLOCK == 216000000\n#else\n#error No valid clock speed selected for STM32F729 Discovery\n#endif\n\n#include \"gpio.h\"\n#include \"uart.h\"\n#include \"rng.h\"\n#include \"sdram.h\"\n#include \"sdio.h\"\n#include \"framebuffer.h\"\n#include \"ltdc.h\"\n#include \"usb.h\"\n#include \"eth.h\"\n\nstatic const struct gpio_config gpio_led0 = {\n    .base=GPIOB,\n    .pin=GPIO0,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led0\"\n};\n\nstatic const struct gpio_config gpio_led1 = {\n    .base=GPIOB,\n    .pin=GPIO7,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led1\"\n};\nstatic const struct gpio_config gpio_led2 = {\n    .base=GPIOB,\n    .pin=GPIO14,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led2\"\n};\n\nstatic const struct gpio_config gpio_button = {\n    .base=GPIOI,\n    .pin=GPIO11,\n    .mode=GPIO_MODE_INPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_PULLUP,\n    .name=\"button\"\n};\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_DEVUART\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = USART2,\n        .irq = NVIC_USART2_IRQ,\n        .rcc = RCC_USART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOD,\n            .pin=GPIO5,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOD,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_USART_3\n    {\n        .devidx = 3,\n        .base = USART3,\n        .irq = NVIC_USART3_IRQ,\n        .rcc = RCC_USART3,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOD,\n            .pin=GPIO8,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOD,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_USART_6\n    {\n        .devidx = 6,\n        .base = USART6,\n        .irq = NVIC_USART6_IRQ,\n        .rcc = RCC_USART6,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOG,\n            .pin=GPIO14,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOG,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\n\n/* Setup GPIO Pins for SDIO:\n   PC8 - PC11 - DAT0 thru DAT3\n   PC12 - CLK\n   PD2 - CMD\n*/\nstruct sdio_config sdio_conf = {\n    .devidx = 0,\n    .base = SDIO_BASE,\n    .rcc_reg = (uint32_t *)&RCC_APB2ENR,\n    .rcc_en  = RCC_APB2ENR_SDMMC1EN,\n    .rcc_rst_reg = (uint32_t *)&RCC_APB2RSTR,\n    .rcc_rst  = RCC_APB2RSTR_SDMMC1RST,\n    .card_detect_supported = 0,\n    .pio_dat0 = {\n        .base=GPIOC,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .af = GPIO_AF12,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n\n    },\n    .pio_dat1 = {\n        .base=GPIOC,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat2 = {\n        .base=GPIOC,\n        .pin=GPIO10,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat3 = {\n        .base=GPIOC,\n        .pin=GPIO11,\n        .af = GPIO_AF12,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_clk = {\n        .base=GPIOC,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cmd = {\n        .base=GPIOD,\n        .pin=GPIO2,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF12,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n};\n\nstruct gpio_config stm32eth_mii_pins[] = {\n    {.base=GPIOA, .pin=GPIO1, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII REF CLK\n    {.base=GPIOA, .pin=GPIO2, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDIO\n    {.base=GPIOA, .pin=GPIO7, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII CRS DV\n    //{.base=GPIOB, .pin=GPIO10,.mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXER --> Not connected?\n    {.base=GPIOG, .pin=GPIO11,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXEN\n    {.base=GPIOG, .pin=GPIO13,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD0\n    {.base=GPIOB, .pin=GPIO13,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD1\n    {.base=GPIOC, .pin=GPIO1, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDC\n    {.base=GPIOC, .pin=GPIO4, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD0\n    {.base=GPIOC, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD1\n};\n\nstatic struct eth_config eth_config = {\n    .pio_mii = stm32eth_mii_pins,\n    .n_pio_mii = 10,\n    .pio_phy_reset = {\n        .base=GPIOE,\n        .pin=GPIO2,\n        .mode=GPIO_MODE_OUTPUT,\n        .optype=GPIO_OTYPE_PP,\n    },\n    .has_phy_reset = 1\n};\n\nstatic struct usb_pio_config_fs pio_usbfs = {\n    .pio_vbus = {\n        .base=GPIOA,\n        .pin=GPIO8,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dm =   {\n        .base=GPIOA,\n        .pin=GPIO11,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    },\n    .pio_dp =   {\n        .base=GPIOA,\n        .pin=GPIO12,\n        .mode=GPIO_MODE_AF,\n        .af=GPIO_AF10,\n        .pullupdown=GPIO_PUPD_NONE,\n    }\n};\n\nstatic struct usb_config usb_guest = {\n    .dev_type = USB_DEV_FS,\n    .otg_mode = USB_MODE_GUEST,\n    .pio.fs = &pio_usbfs\n};\n\nint machine_init(void)\n{\n    int i = 0;\n    rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3);\n    gpio_create(NULL, &gpio_led0);\n    gpio_create(NULL, &gpio_led1);\n    gpio_create(NULL, &gpio_led2);\n//    gpio_create(NULL, &gpio_button);\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n    rng_create(1, RCC_RNG);\n    sdio_conf.rcc_reg = (uint32_t *)&RCC_APB2ENR;\n    sdio_conf.rcc_en  = RCC_APB2ENR_SDMMC1EN;\n    sdio_init(&sdio_conf);\n    usb_init(&usb_guest);\n    ethernet_init(&eth_config);\n    return 0;\n}\n\n"
  },
  {
    "path": "kernel/stm32f7/stm32f769discovery.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include <unicore-mx/stm32/rcc.h>\n#include <unicore-mx/stm32/usart.h>\n#include <unicore-mx/cm3/nvic.h>\n#include <unicore-mx/stm32/f7/usart.h>\n\n#if CONFIG_SYS_CLOCK == 216000000\n#else\n#error No valid clock speed selected for STM32F729 Discovery\n#endif\n\n#include \"gpio.h\"\n#include \"uart.h\"\n#include \"rng.h\"\n#include \"sdram.h\"\n#include \"sdio.h\"\n#include \"framebuffer.h\"\n#include \"ltdc.h\"\n#include \"usb.h\"\n#include \"eth.h\"\n\nstatic const struct gpio_config gpio_led[2] = {\n    {\n    .base=GPIOJ,\n    .pin=GPIO13,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led0\"\n    },\n    {\n    .base=GPIOJ,\n    .pin=GPIO5,\n    .mode=GPIO_MODE_OUTPUT,\n    .optype=GPIO_OTYPE_PP,\n    .name=\"led1\"\n    },\n};\n\nstatic const struct gpio_config gpio_button = {\n    .base=GPIOA,\n    .pin=GPIO0,\n    .mode=GPIO_MODE_INPUT,\n    .optype=GPIO_OTYPE_PP,\n    .pullupdown=GPIO_PUPD_PULLUP,\n    .name=\"button\"\n};\n\nstatic const struct uart_config uart_configs[] = {\n#ifdef CONFIG_DEVUART\n#ifdef CONFIG_USART_1\n    {\n        .devidx = 1,\n        .base = USART1,\n        .irq = NVIC_USART1_IRQ,\n        .rcc = RCC_USART1,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO10,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO9,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_USART_2\n    {\n        .devidx = 2,\n        .base = USART2,\n        .irq = NVIC_USART2_IRQ,\n        .rcc = RCC_USART2,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOA,\n            .pin=GPIO3,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOA,\n            .pin=GPIO2,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF7,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#ifdef CONFIG_USART_6\n    {\n        .devidx = 6,\n        .base = USART6,\n        .irq = NVIC_USART6_IRQ,\n        .rcc = RCC_USART6,\n        .baudrate = 115200,\n        .stop_bits = USART_STOPBITS_1,\n        .data_bits = 8,\n        .parity = USART_PARITY_NONE,\n        .flow = USART_FLOWCONTROL_NONE,\n        .pio_tx = {\n            .base=GPIOC,\n            .pin=GPIO6,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .speed=GPIO_OSPEED_25MHZ,\n            .optype=GPIO_OTYPE_PP,\n        },\n        .pio_rx = {\n            .base=GPIOC,\n            .pin=GPIO7,\n            .mode=GPIO_MODE_AF,\n            .af=GPIO_AF8,\n            .pullupdown=GPIO_PUPD_NONE\n        },\n    },\n#endif\n#endif\n};\n#define NUM_UARTS (sizeof(uart_configs) / sizeof(struct uart_config))\n\nstruct sdio_config sdio_conf = {\n    .devidx = 0,\n    .base = SDIO2_BASE,\n    .rcc_reg = (uint32_t *)&RCC_APB2ENR,\n    .rcc_en  = RCC_APB2ENR_SDMMC2EN,\n    .rcc_rst_reg = (uint32_t *)&RCC_APB2RSTR,\n    .rcc_rst  = RCC_APB2RSTR_SDMMC2RST,\n    .card_detect_supported = 1,\n    .pio_dat0 = {\n        .base=GPIOG,\n        .pin=GPIO9,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .af = GPIO_AF11,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n\n    },\n    .pio_dat1 = {\n        .base=GPIOG,\n        .pin=GPIO10,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF11,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat2 = {\n        .base=GPIOB,\n        .pin=GPIO3,\n        .af = GPIO_AF10,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_dat3 = {\n        .base=GPIOB,\n        .pin=GPIO4,\n        .af = GPIO_AF10,\n        .mode=GPIO_MODE_AF,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_clk = {\n        .base=GPIOD,\n        .pin=GPIO6,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF11,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cmd = {\n        .base=GPIOD,\n        .pin=GPIO7,\n        .mode=GPIO_MODE_AF,\n        .af = GPIO_AF11,\n        .speed=GPIO_OSPEED_100MHZ,\n        .optype=GPIO_OTYPE_PP,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n    .pio_cd = {\n        .base=GPIOI,\n        .pin=GPIO15,\n        .mode=GPIO_MODE_INPUT,\n        .pullupdown=GPIO_PUPD_PULLUP\n    },\n};\n\nstruct gpio_config stm32eth_mii_pins[] = {\n    {.base=GPIOA, .pin=GPIO1, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII REF CLK\n    {.base=GPIOA, .pin=GPIO2, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDIO\n    {.base=GPIOA, .pin=GPIO7, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII CRS DV\n    {.base=GPIOD, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXER\n    {.base=GPIOG, .pin=GPIO11,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXEN\n    {.base=GPIOG, .pin=GPIO13,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD0\n    {.base=GPIOG, .pin=GPIO14,.mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // RMII TXD1\n    {.base=GPIOC, .pin=GPIO1, .mode=GPIO_MODE_AF, .optype=GPIO_OTYPE_PP, .af=GPIO_AF11}, // MDC\n    {.base=GPIOC, .pin=GPIO4, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD0\n    {.base=GPIOC, .pin=GPIO5, .mode=GPIO_MODE_AF, .af=GPIO_AF11},                        // RMII RXD1\n};\n\nstatic struct eth_config eth_config = {\n    .pio_mii = stm32eth_mii_pins,\n    .n_pio_mii = sizeof(stm32eth_mii_pins)/sizeof(struct gpio_config),\n    .pio_phy_reset = {},\n    .has_phy_reset = 0\n};\n\n/* TODO:  HS pios */\n/*\nstatic struct usb_config usb_guest = {\n    .dev_type = USB_DEV_HS,\n    .otg_mode = USB_MODE_GUEST,\n};\n*/\n\nint machine_init(void)\n{\n    int i = 0;\n    rcc_clock_setup_hse_3v3(&rcc_hse_25mhz_3v3);\n    gpio_create(NULL, &gpio_led[0]);\n    gpio_create(NULL, &gpio_led[1]);\n    gpio_create(NULL, &gpio_button);\n    for (i = 0; i < NUM_UARTS; i++) {\n        uart_create(&uart_configs[i]);\n    }\n    rng_create(1, RCC_RNG);\n    sdio_init(&sdio_conf);\n    //usb_init(&usb_guest);\n    ethernet_init(&eth_config);\n    return 0;\n}\n\n"
  },
  {
    "path": "kernel/string.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent, brabo\n *\n */\n\n#include <stddef.h>\n#include <string.h>\n\nvoid *memset(void *s, int c, size_t n)\n{\n\tunsigned char *d = (unsigned char *)s;\n\n\twhile (n--) {\n\t\t*d++ = (unsigned char)c;\n\t}\n\n\treturn s;\n}\n\nchar *strcat(char *dest, const char *src)\n{\n    int i = 0;\n    int j = strlen(dest);\n\n    for (i = 0; i < strlen(src); i++) {\n        dest[j++] = src[i];\n    }\n    dest[j] = '\\0';\n\n    return dest;\n}\n\nint strcmp(const char *s1, const char *s2)\n{\n    int diff = 0;\n\n    while (!diff && *s1) {\n        diff = (int)*s1 - (int)*s2;\n        s1++;\n        s2++;\n    }\n\n\treturn diff;\n}\n\nint strcasecmp(const char *s1, const char *s2)\n{\n    int diff = 0;\n\n    while (!diff && *s1) {\n        diff = (int)*s1 - (int)*s2;\n\n        if ((diff == 'A' - 'a') || (diff == 'a' - 'A'))\n            diff = 0;\n\n        s1++;\n        s2++;\n    }\n\n\treturn diff;\n}\n\nsize_t strlen(const char *s)\n{\n    int i = 0;\n\n    while (s[i] != 0)\n        i++;\n\n    return i;\n}\n\nchar *strncat(char *dest, const char *src, size_t n)\n{\n    int i = 0;\n    int j = strlen(dest);\n\n    for (i = 0; i < strlen(src); i++) {\n        if (j >= (n - 1)) {\n            break;\n        }\n        dest[j++] = src[i];\n    }\n    dest[j] = '\\0';\n\n    return dest;\n}\n\nint strncmp(const char *s1, const char *s2, size_t n)\n{\n    int diff = 0;\n\n    while (n > 0) {\n        diff = (unsigned char)*s1 - (unsigned char)*s2;\n        if (diff || !*s1)\n            break;\n        s1++;\n        s2++;\n        n--;\n    }\n\n    return diff;\n}\n\nvoid *memcpy(void *dst, const void *src, size_t n)\n{\n    int i;\n    const char *s = (const char *)src;\n    char *d = (char *)dst;\n\n    for (i = 0; i < n; i++) {\n        d[i] = s[i];\n    }\n\n    return dst;\n}\n\nchar *strncpy(char *dst, const char *src, size_t n)\n{\n    int i;\n\n    for (i = 0; i < n; i++) {\n        dst[i] = src[i];\n        if (src[i] == '\\0')\n            break;\n    }\n\n    return dst;\n}\n\nchar *strcpy(char *dst, const char *src)\n{\n    int i = 0;\n\n    while(1 < 2) {\n        dst[i] = src[i];\n        if (src[i] == '\\0')\n            break;\n        i++;\n    }\n\n    return dst;\n}\n\nint memcmp(const void *_s1, const void *_s2, size_t n)\n{\n    int diff = 0;\n    const unsigned char *s1 = (const unsigned char *)_s1;\n    const unsigned char *s2 = (const unsigned char *)_s2;\n\n    while (!diff && n) {\n        diff = (int)*s1 - (int)*s2;\n        s1++;\n        s2++;\n        n--;\n    }\n\n\treturn diff;\n}\n"
  },
  {
    "path": "kernel/string.h",
    "content": "#ifndef FLIBC_STRING_H\n#define FLIBC_STRING_H\n\n#include <stddef.h>\n\nextern void * memset(void *s, int c, size_t n);\nextern void *memcpy(void *dst, const void *src, size_t n);\nextern int memcmp(const void *s1, const void *s2, size_t n);\nextern int strcmp(const char *s1, const char *s2);\nextern int strncmp(const char *s1, const char *s2, size_t n);\nextern char *strcat(char *dest, const char *src);\nextern char *strncat(char *dest, const char *src, size_t n);\nextern size_t strlen(const char *s);\nextern char *strcpy(char *dst, const char *src);\nchar *strncpy(char *dst, const char *src, size_t n);\n\n\n#endif /* FLIBC_STRING_H */\n"
  },
  {
    "path": "kernel/sys.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n\n#include \"frosted.h\"\n#include \"sys/frosted.h\"\n#include \"sys/frosted-io.h\"\n#include \"sys/reboot.h\"\n#include \"lowpower.h\"\n#include <time.h>\n#include <unicore-mx/cm3/scb.h>\n\n#ifndef CLOCK_MONOTONIC\n# define CLOCK_MONOTONIC (4)\n#endif\n\nstruct timeval_kernel\n{\n    /* Assuming newlib time_t is long */\n    long tv_sec;\n    long tv_usec;\n};\n\n#ifdef CONFIG_LOWPOWER\nint sys_suspend_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    if (arg1 > 0) {\n        lowpower_sleep(0, arg1);\n    }\n    return 0;\n}\n\nint sys_standby_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    if (arg1 > 0) {\n        lowpower_sleep(1, arg1);\n    }\n    return 0;\n}\n#else \nint sys_suspend_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    return -ENOSYS;\n}\n\nint sys_standby_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    return -ENOSYS;\n}\n#endif\n\n#ifndef CONFIG_PTY_UNIX\nint sys_ptsname_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    return -ENOSYS;\n}\n#endif\n\nint sys_test_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    return (arg1 + (arg2 << 8));\n}\n\nint sys_thread_create_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    /* Deprecated. */\n    return -1;\n}\n\nint sys_thread_join_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    /* Deprecated. */\n    return -1;\n}\n\nint sys_execb_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    /* Deprecated. */\n    return -1;\n}\n\n\nint sys_clock_gettime_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    if (arg2) {\n        struct timeval_kernel *now = (struct timeval_kernel *)arg2;\n        if ((clockid_t)arg1 == CLOCK_MONOTONIC) {\n            now->tv_sec = jiffies / 1000;\n            now->tv_usec = (jiffies % 1000) * 1000;\n        } else if ((clockid_t)arg1 == CLOCK_REALTIME) {\n            now->tv_sec = rt_offset + (jiffies / 1000);\n            now->tv_usec = ((jiffies % 1000) * 1000) * 1000;\n        }\n    }\n    return 0;\n}\n\nint sys_clock_settime_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    if ((clockid_t)arg1 == CLOCK_MONOTONIC) {\n        return -EPERM;\n    }\n    if (arg2 && ((clockid_t)arg1 == CLOCK_REALTIME)) {\n        struct timeval_kernel *now = (struct timeval_kernel *)arg2;\n        unsigned int temp = now->tv_sec;\n        temp = temp + (now->tv_usec / 1000 / 1000);\n        rt_offset = temp - (jiffies / 1000);\n    }\n    return 0;\n}\n\nint sys_reboot_hdlr(uint32_t fadeoff, int cmd, uint32_t interval)\n{\n    if (fadeoff != SYS_FROSTED_FADEOFF)\n        return -EINVAL;\n    switch(cmd) {\n        case RB_REBOOT:\n            scb_reset_system(); /* Never returns. */\n            break;\n        case RB_STANDBY:\n            lowpower_sleep(1, interval);\n            break;\n        case RB_SUSPEND:\n            lowpower_sleep(0, interval);\n            return 0;\n        default:\n            return -ENOENT;\n    }\n    return -EFAULT;\n}\n\n\nstruct utsname {\n    char sysname[16];    /* Operating system name (e.g., \"Frosted\") */\n    char nodename[16];   /* Name within network */\n    char release[16];    /* Operating system release (e.g., \"16.03\") */\n    char version[16];    /* Operating system version (e.g., \"16\") */\n    char machine[16];    /* Hardware identifier */\n    char domainname[16]; /* NIS or YP domain name */\n};\n\nconst struct utsname uts_frosted = { \"Frosted\", \"frosted\", \"16.03\", \"16\", \"arm\", \"local\"};\n\nint sys_uname_hdlr( uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    struct utsname *uts = (struct utsname *)arg1;\n    if (!arg1)\n        return -EFAULT;\n    if (task_ptr_valid(uts))\n        return -EACCES;\n    memcpy(uts, &uts_frosted, sizeof(struct utsname));\n    return 0;\n}\n"
  },
  {
    "path": "kernel/syscall_table_gen.py",
    "content": "#!/usr/bin/python2\n#\n#\n#\n# Add your syscalls here\n#\n# Syntax: [ \"name\", number_of_args, \"name_of_kernelspace_handler\" ]\n#######\n #####\n  ###\n   #\n\nsyscalls = [\n    [\"sleep\", 2, \"sys_sleep_hdlr\"],\n    [\"ptsname\", 3, \"sys_ptsname_hdlr\"],\n    [\"getpid\", 0, \"sys_getpid_hdlr\"],\n    [\"getppid\", 0, \"sys_getppid_hdlr\"],\n    [\"open\", 3, \"sys_open_hdlr\"],\n    [\"close\", 1, \"sys_close_hdlr\"],\n    [\"read\", 3, \"sys_read_hdlr\"],\n    [\"write\", 3, \"sys_write_hdlr\"],\n    [\"seek\", 3, \"sys_seek_hdlr\"],\n    [\"mkdir\", 2, \"sys_mkdir_hdlr\"],\n    [\"unlink\", 1, \"sys_unlink_hdlr\"],\n    [\"malloc\", 1, \"sys_malloc_hdlr\"],\n    [\"free\", 1, \"sys_free_hdlr\"],\n    [\"calloc\", 2, \"sys_calloc_hdlr\"],\n    [\"realloc\", 2, \"sys_realloc_hdlr\"],\n    [\"opendir\", 1, \"sys_opendir_hdlr\"],\n    [\"readdir\", 2, \"sys_readdir_hdlr\"],\n    [\"closedir\",1, \"sys_closedir_hdlr\"],\n    [\"stat\", 2, \"sys_stat_hdlr\"],\n    [\"poll\", 3, \"sys_poll_hdlr\"],\n    [\"ioctl\", 3, \"sys_ioctl_hdlr\"],\n    [\"link\", 2, \"sys_link_hdlr\"],\n    [\"chdir\", 1, \"sys_chdir_hdlr\"],\n    [\"getcwd\", 2, \"sys_getcwd_hdlr\"],\n    [\"sem_init\", 2, \"sys_sem_init_hdlr\"],\n    [\"sem_post\", 1, \"sys_sem_post_hdlr\"],\n    [\"sem_wait\", 2, \"sys_sem_wait_hdlr\"],\n    [\"sem_trywait\", 1, \"sys_sem_trywait_hdlr\"],\n    [\"sem_destroy\", 1, \"sys_sem_destroy_hdlr\"],\n    [\"mutex_init\", 0, \"sys_mutex_init_hdlr\"],\n    [\"mutex_unlock\", 1, \"sys_mutex_unlock_hdlr\"],\n    [\"mutex_lock\", 1, \"sys_mutex_lock_hdlr\"],\n    [\"mutex_destroy\", 1, \"sys_mutex_destroy_hdlr\"],\n    [\"socket\", 3, \"sys_socket_hdlr\"],\n    [\"bind\", 2, \"sys_bind_hdlr\"],\n    [\"accept\", 2, \"sys_accept_hdlr\"],\n    [\"connect\", 2, \"sys_connect_hdlr\"],\n    [\"listen\", 2, \"sys_listen_hdlr\"],\n    [\"sendto\", 5, \"sys_sendto_hdlr\"],\n    [\"recvfrom\", 5, \"sys_recvfrom_hdlr\"],\n    [\"setsockopt\", 5, \"sys_setsockopt_hdlr\"],\n    [\"getsockopt\", 5, \"sys_getsockopt_hdlr\"],\n    [\"shutdown\", 2, \"sys_shutdown_hdlr\"],\n    [\"dup\", 1, \"sys_dup_hdlr\"],\n    [\"dup2\", 2, \"sys_dup2_hdlr\"],\n    [\"mount\", 5, \"sys_mount_hdlr\"],\n    [\"umount\", 2, \"sys_umount_hdlr\"],\n    [\"kill\", 2, \"sys_kill_hdlr\"],\n    [\"isatty\", 1, \"sys_isatty_hdlr\"],\n    [\"exec\", 2, \"sys_exec_hdlr\"],\n    [\"ttyname_r\", 3, \"sys_ttyname_hdlr\"],\n    [\"exit\", 1, \"sys_exit_hdlr\"],\n    [\"tcsetattr\", 3, \"sys_tcsetattr_hdlr\"],\n    [\"tcgetattr\", 2, \"sys_tcgetattr_hdlr\"],\n    [\"tcsendbreak\", 2, \"sys_tcsendbreak_hdlr\"],\n    [\"pipe2\", 2, \"sys_pipe2_hdlr\"],\n    [\"sigaction\", 3, \"sys_sigaction_hdlr\"],\n    [\"sigprocmask\", 3, \"sys_sigprocmask_hdlr\"],\n    [\"sigsuspend\", 1, \"sys_sigsuspend_hdlr\"],\n    [\"vfork\", 0, \"sys_vfork_hdlr\"],\n    [\"waitpid\", 3, \"sys_waitpid_hdlr\"],\n    [\"lstat\", 2, \"sys_lstat_hdlr\"],\n    [\"uname\", 1, \"sys_uname_hdlr\"],\n    [\"getaddrinfo\", 4, \"sys_getaddrinfo_hdlr\"],\n    [\"freeaddrinfo\", 1, \"sys_freeaddrinfo_hdlr\"],\n    [\"fstat\", 2, \"sys_fstat_hdlr\"],\n    [\"getsockname\", 2, \"sys_getsockname_hdlr\"],\n    [\"getpeername\", 2, \"sys_getpeername_hdlr\"],\n    [\"readlink\", 3, \"sys_readlink_hdlr\"],\n    [\"fcntl\", 3, \"sys_fcntl_hdlr\"],\n    [\"setsid\", 0, \"sys_setsid_hdlr\"],\n    [\"ptrace\", 4, \"sys_ptrace_hdlr\"],\n    [\"reboot\", 3, \"sys_reboot_hdlr\"],\n    [\"getpriority\", 2, \"sys_getpriority_hdlr\"],\n    [\"setpriority\", 3, \"sys_setpriority_hdlr\"],\n    [\"ftruncate\", 2, \"sys_ftruncate_hdlr\"],\n    [\"truncate\", 2, \"sys_truncate_hdlr\"],\n    [\"pthread_create\", 4, \"sys_pthread_create_hdlr\"],\n    [\"pthread_exit\", 1, \"sys_pthread_exit_hdlr\"],\n    [\"pthread_join\", 2, \"sys_pthread_join_hdlr\"],\n    [\"pthread_detach\", 1, \"sys_pthread_detach_hdlr\"],\n    [\"pthread_cancel\", 1, \"sys_pthread_cancel_hdlr\"],\n    [\"pthread_self\", 0, \"sys_pthread_self_hdlr\"],\n    [\"pthread_setcancelstate\", 2, \"sys_pthread_setcancelstate_hdlr\"],\n    [\"sched_yield\", 0, \"sys_sched_yield_hdlr\"],\n    [\"pthread_mutex_init\", 2, \"sys_pthread_mutex_init_hdlr\"],\n    [\"pthread_mutex_destroy\", 1, \"sys_pthread_mutex_destroy_hdlr\"],\n    [\"pthread_mutex_lock\", 1, \"sys_pthread_mutex_lock_hdlr\"],\n    [\"pthread_mutex_trylock\", 1, \"sys_pthread_mutex_trylock_hdlr\"],\n    [\"pthread_mutex_unlock\", 1, \"sys_pthread_mutex_unlock_hdlr\"],\n    [\"pthread_kill\", 2, \"sys_pthread_kill_hdlr\"],\n    [\"clock_settime\", 2, \"sys_clock_settime_hdlr\"],\n    [\"clock_gettime\", 2, \"sys_clock_gettime_hdlr\"],\n    [\"pthread_key_create\", 2, \"sys_pthread_key_create_hdlr\"],\n    [\"pthread_setspecific\", 2, \"sys_pthread_setspecific_hdlr\"],\n    [\"pthread_getspecific\", 2, \"sys_pthread_getspecific_hdlr\"],\n    [\"alarm\", 1, \"sys_alarm_hdlr\"],\n    [\"ualarm\", 2, \"sys_ualarm_hdlr\"],\n]\n\n   #\n  ###\n #####\n#######\n#################################################################\nhdr = open(\"kernel/frosted-headers/include/sys/frosted.h\", \"w\")\nusercode = open(\"kernel/frosted-headers/sys/frosted_syscalls.c\", \"w\")\ncode = open(\"kernel/syscall_table.c\", \"w\")\n\nhdr.write(\"/* The file frosted.h is auto generated. DO NOT EDIT, CHANGES WILL BE LOST. */\\n/* If you want to add syscalls, use syscall_table_gen.py  */\\n\\n\")\nusercode.write(\"/* The file frosted_syscalls.c is auto generated. DO NOT EDIT, CHANGES WILL BE LOST. */\\n/* If you want to add syscalls, use syscall_table_gen.py  */\\n\\n#include <stdint.h>\\n#include \\\"sys/frosted.h\\\"\\n\")\ncode.write(\"/* The file syscall_table.c is auto generated. DO NOT EDIT, CHANGES WILL BE LOST. */\\n/* If you want to add syscalls, use syscall_table_gen.py  */\\n\\n#include \\\"frosted.h\\\"\\n#include \\\"sys/frosted.h\\\"\\n\")\n\nfor n in range(len(syscalls)):\n    name = syscalls[n][0]\n    hdr.write(\"#define SYS_%s \\t\\t\\t(%d)\\n\" % (name.upper(), n))\nhdr.write(\"#define _SYSCALLS_NR (%d) /* We have %d syscalls! */\\n\" % (len(syscalls), len(syscalls)))\n\nfor n in range(len(syscalls)):\n    name = syscalls[n][0]\n    tp = syscalls[n][1]\n    usercode.write( \"/* Syscall: %s(%d arguments) */\\n\" % (name, tp))\n    if (tp == 0):\n        usercode.write( \"int sys_%s(void){\\n\" % name)\n        usercode.write( \"    return syscall(SYS_%s, 0, 0, 0, 0, 0); \\n\" % name.upper())\n        usercode.write( \"}\\n\")\n        usercode.write(\"\\n\")\n    if (tp == 1):\n        usercode.write( \"int sys_%s(uint32_t arg1){\\n\" % name)\n        usercode.write( \"    return syscall(SYS_%s, arg1, 0, 0, 0, 0); \\n\" % name.upper())\n        usercode.write( \"}\\n\")\n        usercode.write(\"\\n\")\n    if (tp == 2):\n        usercode.write( \"int sys_%s(uint32_t arg1, uint32_t arg2){\\n\" % name)\n        usercode.write( \"    return syscall(SYS_%s, arg1, arg2, 0, 0, 0); \\n\" % name.upper())\n        usercode.write( \"}\\n\")\n        usercode.write(\"\\n\")\n    if (tp == 3):\n        usercode.write( \"int sys_%s(uint32_t arg1, uint32_t arg2, uint32_t arg3){\\n\" % name)\n        usercode.write( \"    return syscall(SYS_%s, arg1, arg2, arg3, 0,  0); \\n\" % name.upper())\n        usercode.write( \"}\\n\")\n        usercode.write(\"\\n\")\n    if (tp == 4):\n        usercode.write( \"int sys_%s(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4){\\n\" % name)\n        usercode.write( \"    return syscall(SYS_%s, arg1, arg2, arg3, arg4, 0); \\n\" % name.upper())\n        usercode.write( \"}\\n\")\n        usercode.write(\"\\n\")\n    if (tp == 5):\n        usercode.write( \"int sys_%s(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5){\\n\" % name)\n        usercode.write( \"    return syscall(SYS_%s, arg1, arg2, arg3, arg4, arg5); \\n\" % name.upper())\n        usercode.write( \"}\\n\")\n        usercode.write(\"\\n\")\n\nusercode.close()\n\n\ncode.write(\"/* External handlers (defined elsewhere) : */ \\n\")\nfor n in range(len(syscalls)):\n    name = syscalls[n][0]\n    call = syscalls[n][2]\n    code.write( \"extern int %s(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);\\n\" % call)\ncode.write(\"\\n\")\n\ncode.write(\"void syscalls_init(void) {\\n\")\nfor n in range(len(syscalls)):\n    call = syscalls[n][2]\n    code.write( \"\\tsys_register_handler(%d, %s);\\n\" % (n, call) );\ncode.write(\"}\\n\")\ncode.close()\n"
  },
  {
    "path": "kernel/syscall_vector.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n\n#include <stdint.h>\n/* Syscall table Vector array */\nextern int sys_setclock( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_sleep( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_suspend( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_thread_create( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_thread_join( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_test( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_getpid( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_getppid( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_open( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_close( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_read( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_write( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_seek( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_mkdir( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_unlink( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_gettimeofday( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_malloc( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_mem_init( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_free( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_calloc( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_realloc( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_opendir( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_readdir( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_closedir( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_stat( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_poll( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_ioctl( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_link( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_chdir( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_getcwd( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_sem_init( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_sem_post( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_sem_wait( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_sem_destroy( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_mutex_init( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_mutex_unlock( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_mutex_lock( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_mutex_destroy( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_socket( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_bind( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_accept( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_connect( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_listen( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_sendto( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_recvfrom( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_setsockopt( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_getsockopt( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_shutdown( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_dup( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_dup2( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_mount( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_umount( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_kill( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_isatty( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_exec( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_ttyname_r( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_exit( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_tcsetattr( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_tcgetattr( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_tcsendbreak( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nextern int sys_pipe2( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t );\nint __attribute__((used,section(\".syscall_vector\"))) (* const _k__syscall__[61])( uint32_t, uint32_t, uint32_t, uint32_t, uint32_t ) = {\n\tsys_setclock,\n\tsys_sleep,\n\tsys_suspend,\n\tsys_thread_create,\n\tsys_thread_join,\n\tsys_test,\n\tsys_getpid,\n\tsys_getppid,\n\tsys_open,\n\tsys_close,\n\tsys_read,\n\tsys_write,\n\tsys_seek,\n\tsys_mkdir,\n\tsys_unlink,\n\tsys_gettimeofday,\n\tsys_malloc,\n\tsys_mem_init,\n\tsys_free,\n\tsys_calloc,\n\tsys_realloc,\n\tsys_opendir,\n\tsys_readdir,\n\tsys_closedir,\n\tsys_stat,\n\tsys_poll,\n\tsys_ioctl,\n\tsys_link,\n\tsys_chdir,\n\tsys_getcwd,\n\tsys_sem_init,\n\tsys_sem_post,\n\tsys_sem_wait,\n\tsys_sem_destroy,\n\tsys_mutex_init,\n\tsys_mutex_unlock,\n\tsys_mutex_lock,\n\tsys_mutex_destroy,\n\tsys_socket,\n\tsys_bind,\n\tsys_accept,\n\tsys_connect,\n\tsys_listen,\n\tsys_sendto,\n\tsys_recvfrom,\n\tsys_setsockopt,\n\tsys_getsockopt,\n\tsys_shutdown,\n\tsys_dup,\n\tsys_dup2,\n\tsys_mount,\n\tsys_umount,\n\tsys_kill,\n\tsys_isatty,\n\tsys_exec,\n\tsys_ttyname_r,\n\tsys_exit,\n\tsys_tcsetattr,\n\tsys_tcgetattr,\n\tsys_tcsendbreak,\n\tsys_pipe2\n};\n"
  },
  {
    "path": "kernel/systick.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"heap.h\"\n#include \"lowpower.h\"\n#include \"unicore-mx/cm3/nvic.h\"\n#include \"unicore-mx/cm3/systick.h\"\n#include \"unicore-mx/cm3/scb.h\"\n#define SEV() asm volatile (\"sev\")\n\n#ifdef NRF51\n#include \"unicore-mx/nrf/51/ostick.h\"\n#endif\n\nvolatile unsigned int jiffies = 0u;\nvolatile unsigned int _n_int = 0u;\nvolatile int ktimer_check_pending = 0;\nvolatile int sleep_mode = 0;\nstatic int _sched_active = 0;\n\nvoid frosted_scheduler_on(void)\n{\n    nvic_set_priority(NVIC_PENDSV_IRQ, 2);\n    nvic_set_priority(NVIC_SV_CALL_IRQ, 1);\n#ifdef CUSTOM_SYSTICK\n    ostick_init(1, &sys_tick_handler);\n    ostick_start();\n#else\n    nvic_set_priority(NVIC_SYSTICK_IRQ, 0);\n    nvic_enable_irq(NVIC_SYSTICK_IRQ);\n    systick_counter_enable();\n    systick_interrupt_enable();\n#endif\n    _sched_active = 1;\n}\n\nvoid frosted_scheduler_off(void)\n{\n    _sched_active = 0;\n}\n\nvoid __attribute__((weak)) SysTick_Hook(void)\n{\n}\n\ntypedef struct ktimer {\n    uint32_t expire_time;\n    void *arg;\n    void (*handler)(uint32_t time, void *arg);\n} ktimer;\n\nDECLARE_HEAP(ktimer, expire_time);\nstatic struct heap_ktimer *ktimer_list = NULL;\n\n/* Init function */\nvoid ktimer_init(void)\n{\n    ktimer_list = heap_init();\n}\n\n/* Add kernel timer */\nint ktimer_add(uint32_t count, void (*handler)(uint32_t, void *), void *arg)\n{\n    struct ktimer t;\n    int ret;\n    memset(&t, 0, sizeof(t));\n    t.expire_time = jiffies + count;\n    t.handler = handler;\n    t.arg = arg;\n    if (!task_in_syscall())\n        irq_off();\n    ret = heap_insert(ktimer_list, &t);\n    if (!task_in_syscall())\n        irq_on();\n    return ret;\n}\n\n/* Delete kernel timer */\nint ktimer_del(int tid)\n{\n    int ret;\n    if (tid < 0)\n        return -1;\n    if (!task_in_syscall())\n        irq_off();\n    ret = heap_delete(ktimer_list, tid);\n    if (!task_in_syscall())\n        irq_on();\n    return ret;\n}\n\nstatic inline int ktimer_expired(void)\n{\n    struct ktimer *t;\n    return ((ktimer_list) && (ktimer_list->n > 0) &&\n            (t = heap_first(ktimer_list)) && (t->expire_time < jiffies));\n}\n\n\n/* Tasklet that checks expired timers */\nstatic void ktimers_check_tasklet(void *arg)\n{\n    struct ktimer *t;\n    struct ktimer t_previous;\n    int next_t;\n    uint32_t this_timeslice;\n\n    next_t = -1;\n\n    if ((ktimer_list) && (ktimer_list->n > 0)) {\n        irq_off();\n        t = heap_first(ktimer_list);\n        irq_on();\n\n        while ((t) && (t->expire_time < jiffies)) {\n            if (t->handler) {\n                t->handler(jiffies, t->arg);\n            }\n            irq_off();\n            heap_peek(ktimer_list, &t_previous);\n            t = heap_first(ktimer_list);\n            irq_on();\n        }\n        next_t = (t->expire_time - jiffies);\n    }\n\n    ktimer_check_pending = 0;\n}\n\nvoid sys_tick_handler(void)\n{\n    uint32_t next_timer = 0;\n    volatile uint32_t reload = systick_get_reload();\n    uint32_t this_timeslice;\n    SysTick_Hook();\n    jiffies ++;\n    _n_int++;\n\n    if (ktimer_expired()) {\n        task_preempt_all();\n        goto end;\n    }\n\n    if (_sched_active && ((task_timeslice() == 0) || (!task_running()))) {\n        schedule();\n        (void)next_timer;\n    }\nend:\n    if (!ktimer_check_pending) {\n        ktimer_check_pending++;\n        tasklet_add(ktimers_check_tasklet, NULL);\n    }\n}\n"
  },
  {
    "path": "kernel/tasklet.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"unicore-mx/cm3/systick.h\"\n\n#define MAX_TASKLETS 64\n\nstruct tasklet {\n    void (*exe)(void *);\n    void *arg;\n};\n\nstatic struct tasklet tasklet_array[MAX_TASKLETS];\nuint32_t n_tasklets = 0;\nuint32_t max_tasklets = 0;\n\n\nvoid tasklet_add(void (*exe)(void*), void *arg)\n{\n    int i;\n    if (!task_in_syscall())\n\t    irq_off();\n    for (i = 0; i < MAX_TASKLETS; i++) {\n        if (!tasklet_array[i].exe) {\n            tasklet_array[i].exe = exe;\n            tasklet_array[i].arg = arg;\n            n_tasklets++;\n            if (n_tasklets > max_tasklets)\n                max_tasklets = n_tasklets;\n\t    if (!task_in_syscall())\n\t\t    irq_on();\n            return;\n        }\n    }\n    while(1) { /* Too many tasklets. */; }\n\n}\n\nvoid check_tasklets(void)\n{\n    int i;\n    if (n_tasklets == 0)\n        return;\n    irq_off();\n    for (i = 0; i < MAX_TASKLETS; i++) {\n        if (tasklet_array[i].exe) {\n            tasklet_array[i].exe(tasklet_array[i].arg);\n            tasklet_array[i].exe = NULL;\n            tasklet_array[i].arg = NULL;\n            n_tasklets--;\n        }\n    }\n    irq_on();\n}\n"
  },
  {
    "path": "kernel/term.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include <string.h>\n#include <sys/termios.h>\n\nstatic struct module *get_term_mod(int td)\n{\n    struct fnode *f = task_filedesc_get(td);\n    if (f)\n        return f->owner;\n    return NULL;\n}\n\nint sys_tcgetattr_hdlr(int arg1, int arg2)\n{\n    struct termios *t = (struct termios *)arg2;\n    struct module *m;\n    if (task_ptr_valid(t))\n        return -EACCES;\n    m = get_term_mod(arg1);\n    if (m && m->ops.tcgetattr)\n        return m->ops.tcgetattr(arg1, t);\n    else\n        return -EOPNOTSUPP;\n}\n\nint sys_tcsetattr_hdlr(int arg1, int arg2, int arg3)\n{\n    const struct termios *t = (const struct termios *)arg3;\n    struct module *m;\n    if (task_ptr_valid(t))\n        return -EACCES;\n    m = get_term_mod(arg1);\n    if (m && m->ops.tcsetattr)\n        return m->ops.tcsetattr(arg1, arg2, t);\n    else\n        return -EOPNOTSUPP;\n}\n\n\nint sys_tcsendbreak_hdlr(int arg1, int arg2)\n{\n    /* TODO: send SIGINT to self. */\n    return -EOPNOTSUPP;\n}\n"
  },
  {
    "path": "kernel/vfs.c",
    "content": "/*\n *      This file is part of frosted.\n *\n *      frosted is free software: you can redistribute it and/or modify\n *      it under the terms of the GNU General Public License version 2, as\n *      published by the Free Software Foundation.\n *\n *\n *      frosted is distributed in the hope that it will be useful,\n *      but WITHOUT ANY WARRANTY; without even the implied warranty of\n *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *      GNU General Public License for more details.\n *\n *      You should have received a copy of the GNU General Public License\n *      along with frosted.  If not, see <http://www.gnu.org/licenses/>.\n *\n *      Authors: Daniele Lacamera, Maxime Vincent\n *\n */\n#include \"frosted.h\"\n#include \"vfs.h\"\n#include \"string.h\"\n#include \"scheduler.h\"\n#include \"sys/stat.h\"\n\n#define O_MODE(o) ((o & O_ACCMODE))\n#define O_BLOCKING(f) ((f->flags & O_NONBLOCK) == 0)\n\nstruct mountpoint *MTAB = NULL;\n\n/* ROOT entity (\"/\")\n *.\n */\nstatic struct fnode FNO_ROOT = {\n};\n\nstatic void basename_r(const char *path, char *res)\n{\n    char *p;\n    strncpy(res, path, strlen(path) + 1);\n    p = res + strlen(res) - 1;\n    while (p >= res) {\n        if (*p == '/') {\n            *p = '\\0';\n            break;\n        }\n        p--;\n    }\n    if (strlen(res) == 0) {\n        res[0] = '/';\n        res[1] = '\\0';\n    }\n\n}\n\nstatic char *filename(char *path)\n{\n    int len = strlen(path);\n    char *p = path + len - 1;\n    while (p >= path) {\n        if (*p == '/')\n            return (p + 1);\n        p--;\n    }\n    return path;\n}\n\nstatic struct fnode *_fno_search(const char *path, struct fnode *dir, int follow);\n\nstatic int _fno_fullpath(struct fnode *f, char *dst, char **p, int len)\n{\n    int nlen;\n    if (!f)\n        return -EINVAL;\n    if ((f->flags & FL_LINK) == FL_LINK) {\n        f =  _fno_search(f->linkname, &FNO_ROOT, 1);\n    }\n    if (f == &FNO_ROOT) {\n        *p = dst + 1;\n        dst[0] = '/';\n        dst[1] = '\\0';\n        return 0;\n    }\n    if (!*p) {\n        if (!f->parent)\n            return -EINVAL; // what to do, how is this possible?\n        _fno_fullpath(f->parent, dst, p, len);\n    }\n    nlen = strlen(f->fname);\n    if (nlen + (*p - dst) > (len -1))\n        return -ENAMETOOLONG;\n    memcpy(*p, f->fname, nlen);\n    *p += nlen;\n    *(*p) = '/';\n    *p += 1;\n    *(*p + 1) = '\\0';\n    return 0;\n}\n\nint fno_fullpath(struct fnode *f, char *dst, int len)\n{\n    char *p = NULL;\n    int ret;\n    ret =  _fno_fullpath(f, dst, &p, len);\n    if (ret == 0)  {\n        int nlen = strlen(dst);\n        if (nlen > 1) {\n            /* Remove trailing \"/\" */\n            dst[--nlen] = '\\0';\n            while (dst[nlen - 1] == '/') {\n                dst[nlen - 1] = '\\0';\n                nlen--;\n            }\n        }\n        return nlen;\n    }\n    return -ENOENT;\n}\n\nstatic int path_abs(char *src, char *dst, int len)\n{\n    struct fnode *f = task_getcwd();\n    if (src[0] == '/')\n        strncpy(dst, src, len);\n    else {\n        if (fno_fullpath(f, dst, len) > 0) {\n            while (dst[strlen(dst) - 1] == '/')\n                dst[strlen(dst) - 1] = '\\0';\n\n            strncat(dst, \"/\", len);\n            strncat(dst, src, len);\n            return 0;\n        }\n    }\n    return 0;\n}\n\nstatic struct fnode *fno_create_file(char *path)\n{\n    char *base = kalloc(strlen(path) + 1);\n    struct module *owner = NULL;\n    struct fnode *parent;\n    struct fnode *f = NULL;\n    if (!base)\n        return NULL;\n    basename_r(path, base);\n    parent = fno_search(base);\n    kfree(base);\n    if (!parent)\n        return NULL;\n    if ((parent->flags & FL_DIR) == 0)\n        return NULL;\n\n    if (parent) {\n        owner = parent->owner;\n    }\n    f = fno_create(owner, filename(path), parent);\n    if (f)\n        f->flags = 0;\n    return f;\n}\n\nstatic struct fnode *fno_link(char *src, char *dst)\n{\n    struct fnode *file;\n    struct fnode *link;\n    int file_name_len;\n    char p_src[MAX_FILE];\n    char p_dst[MAX_FILE];\n\n    path_abs(src, p_src, MAX_FILE);\n    path_abs(dst, p_dst, MAX_FILE);\n\n    file = fno_search(p_src);\n    if (!file)\n        return NULL;\n\n    link = fno_create_file(p_dst);\n    if (!link)\n        return NULL;\n\n    file_name_len = strlen(p_src);\n\n    link->flags |= FL_LINK;\n    link->linkname = kalloc(file_name_len + 1);\n    if (!link->linkname) {\n        fno_unlink(link);\n        return NULL;\n    }\n    strncpy(link->linkname, p_src, file_name_len + 1);\n    return link;\n}\n\nint vfs_symlink(char *file, char *link)\n{\n    if (fno_link(file, link) != NULL)\n        return 0;\n    else return -EINVAL;\n}\n\nstatic void mkdir_links(struct fnode *fno)\n{\n    char path[MAX_FILE], selfl[MAX_FILE], parentl[MAX_FILE], path_basename[MAX_FILE];\n    fno_fullpath(fno, path, MAX_FILE -4);\n    strcpy(selfl, path);\n    strcpy(parentl, path);\n    strcat(selfl, \"/.\");\n    strcat(parentl, \"/..\");\n    if (fno) {\n        fno_link(path, selfl);\n        basename_r(path, path_basename);\n        fno_link(path_basename, parentl);\n    }\n}\n\nstatic struct fnode *fno_create_dir(char *path, uint32_t flags)\n{\n    struct fnode *fno = fno_create_file(path);\n    if (fno) {\n        fno->flags |= (FL_DIR | flags);\n    }\n    mkdir_links(fno);\n    return fno;\n}\n\n\nstatic const char *path_walk(const char *path)\n{\n    const char *p = path;\n\n    if (*p == '/') {\n        while(*p == '/')\n            p++;\n        return p;\n    }\n\n    while ((*p != '\\0') && (*p != '/'))\n        p++;\n\n    if (*p == '/')\n        p++;\n\n    if (*p == '\\0')\n        return NULL;\n\n    return p;\n}\n\n\n/* Returns:\n * 0 = if path does not match\n * 1 = if path is in the right dir, need to walk more\n * 2 = if path is found!\n */\n\nstatic int path_check(const char *path, const char *dirname)\n{\n\n    int i = 0;\n    for (i = 0; dirname[i]; i++) {\n        if (path[i] != dirname[i])\n            return 0;\n    }\n\n    if (path[i] == '\\0')\n        return 2;\n\n    if (path[i] == '/')\n        return 1;\n\n    if (i > 0 && (path[i - 1] == '/' && dirname[i - 1] == '/'))\n        return 1;\n\n    return 0;\n}\n\n\nstatic struct fnode *_fno_search(const char *path, struct fnode *dir, int follow)\n{\n    struct fnode *cur;\n    char link[MAX_FILE];\n    int check = 0;\n    if (dir == NULL)\n        return NULL;\n\n    check = path_check(path, dir->fname);\n\n    /* Does not match, try another item */\n    if (check == 0) {\n        if (!dir->next)\n            return NULL;\n        return _fno_search(path, dir->next, follow);\n    }\n\n    /* Item is found! */\n    if (check == 2) {\n        /* If it's a symlink, restart check */\n        if (follow && ((dir->flags & FL_LINK) == FL_LINK)) {\n            return _fno_search(dir->linkname, &FNO_ROOT, 1);\n        }\n        return dir;\n    }\n\n    /* path is correct, need to walk more */\n    if( (dir->flags & FL_LINK ) == FL_LINK ){\n    /* passing through a symlink */\n        strcpy( link, dir->linkname );\n        strcat( link, \"/\" );\n        strcat( link, path_walk(path));\n        return _fno_search( link, &FNO_ROOT, follow );\n    }\n    return _fno_search(path_walk(path), dir->children, follow);\n}\n\nstruct fnode *fno_search(const char *_path)\n{\n    int i, len;\n    struct fnode *fno = NULL;\n    char *path = NULL;\n    if (!_path)\n        return NULL;\n\n    len = strlen(_path);\n    if (!len)\n        return NULL;\n\n    path = kcalloc(len + 1, 1);\n    if (!path)\n        return NULL;\n\n    memcpy(path, _path, len + 1);\n\n    i = len - 1;\n    while (i > 0) {\n        if (path[i] == '/')\n            path[i] = '\\0';\n        else\n            break;\n        --i;\n    }\n    if (strlen(path) > 0) {\n        fno = _fno_search(path, &FNO_ROOT, 1);\n    }\n    kfree(path);\n    return fno;\n}\n\nstruct fnode *fno_search_nofollow(const char *path)\n{\n    return _fno_search(path, &FNO_ROOT, 0);\n}\n\nstatic struct fnode *_fno_create(struct module *owner, const char *name, struct fnode *parent)\n{\n    struct fnode *fno = kcalloc(sizeof(struct fnode), 1);\n    int nlen = strlen(name);\n    if (!fno)\n        return NULL;\n\n    fno->fname = kalloc(nlen + 1);\n    if (!fno->fname){\n        kfree(fno);\n        return NULL;\n    }\n\n    memcpy(fno->fname, name, nlen + 1);\n    if (!parent) {\n        parent = &FNO_ROOT;\n    }\n\n    fno->parent = parent;\n    fno->next = fno->parent->children;\n    fno->parent->children = fno;\n\n    fno->children = NULL;\n    fno->owner = owner;\n    return fno;\n}\n\nstruct fnode *fno_create(struct module *owner, const char *name, struct fnode *parent)\n{\n    struct fnode *fno = _fno_create(owner, name, parent);\n    if (fno && parent && parent->owner && parent->owner->ops.creat)\n        parent->owner->ops.creat(fno);\n    fno->flags |= FL_RDWR;\n    return fno;\n}\n\nstruct fnode *fno_create_wronly(struct module *owner, const char *name, struct fnode *parent)\n{\n    struct fnode *fno = _fno_create(owner, name, parent);\n    if (fno && parent && parent->owner && parent->owner->ops.creat)\n        parent->owner->ops.creat(fno);\n    fno->flags = FL_WRONLY;\n    return fno;\n}\n\nstruct fnode *fno_create_rdonly(struct module *owner, const char *name, struct fnode *parent)\n{\n    struct fnode *fno = _fno_create(owner, name, parent);\n    if (fno && parent && parent->owner && parent->owner->ops.creat)\n        parent->owner->ops.creat(fno);\n    fno->flags = FL_RDONLY;\n    return fno;\n}\n\nstruct fnode *fno_mkdir(struct module *owner, const char *name, struct fnode *parent)\n{\n    struct fnode *fno = _fno_create(owner, name, parent);\n    fno->flags |= (FL_DIR | FL_RDWR);\n    if (parent && parent->owner && parent->owner->ops.creat)\n        parent->owner->ops.creat(fno);\n    mkdir_links(fno);\n    return fno;\n}\n\nvoid fno_unlink(struct fnode *fno)\n{\n    struct fnode *dir;\n\n    if (!fno)\n        return;\n    dir = fno->parent;\n\n    if (fno && fno->owner && fno->owner->ops.unlink)\n        fno->owner->ops.unlink(fno);\n\n    if (!fno)\n        return;\n\n    if (dir) {\n        struct fnode *child = dir->children;\n        while (child) {\n            if (child == fno) {\n                dir->children = fno->next;\n                break;\n            }\n            if (child->next == fno) {\n                child->next = fno->next;\n                break;\n            }\n            child = child->next;\n        }\n    }\n\n\n    kfree(fno->fname);\n    kfree(fno);\n}\n\nint sys_readlink_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    char *path = (char*)arg1;\n    char *buf = (char*)arg2;\n    size_t size = (size_t)arg3;\n    int len;\n    char abs_p[MAX_FILE];\n    struct fnode *fno;\n    if(!buf)\n        return -EINVAL;\n    if (task_ptr_valid(buf) || task_ptr_valid(path))\n        return -EACCES;\n    path_abs(path, abs_p, MAX_FILE);\n    fno = fno_search_nofollow(abs_p);\n    if(!fno)\n        return -ENOENT;\n    else if (fno->flags & FL_LINK)\n        strncpy(buf, fno->linkname, size);\n    else\n        return -EINVAL;\n    len = strlen(fno->linkname);\n    return len < size ? len : size;\n}\n\nint sys_exec_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    char *path = (char *)arg1;\n    char *arg = (char *)arg2;\n    struct fnode *f;\n    struct vfs_info *vfsi = NULL;\n    if (task_ptr_valid(arg) || task_ptr_valid(path))\n        return -EACCES;\n\n    f = fno_search(path);\n    if (f && f->owner && (f->flags & FL_EXEC) && f->owner->ops.exe) {\n        vfsi = (struct vfs_info *)f->owner->ops.exe(f, arg);\n        if (vfsi)\n            scheduler_exec(vfsi, arg);\n    }\n    return -EINVAL;\n}\n\nint sys_open_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    char *rel_path = (char *)arg1;\n    struct fnode *f;\n    uint32_t flags = arg2;\n    char path[MAX_FILE];\n    int ret;\n    if (task_ptr_valid(rel_path))\n        return -EACCES;\n\n    path_abs(rel_path, path, MAX_FILE);\n    f = fno_search(path);\n    if (f && f->owner && f->owner->ops.open) {\n        if ((O_MODE(flags) != O_RDONLY) && ((f->flags & FL_WRONLY)== 0))\n            return -EPERM;\n        ret = f->owner->ops.open(path, flags);\n        if (ret >= 0) {\n            task_fd_setmask(ret, flags);\n            task_fd_set_flags(ret, flags);\n            task_fd_set_off(f, 0);\n        }\n        return ret;\n    }\n\n    if ((flags & O_CREAT) == 0) {\n        f = fno_search(path);\n    } else {\n        if ((O_MODE(flags)) == O_RDONLY)\n            return -EPERM;\n        f = fno_search(path);\n        if (flags & O_EXCL) {\n            if (f != NULL)\n                return -EEXIST;\n        }\n        if (f && (flags & O_TRUNC)) {\n            if (f) {\n                fno_unlink(f);\n                f = NULL;\n            }\n\n        }\n        if (!f)\n            f = fno_create_file(path);\n\n        /* TODO: Parse arg3 & 0x1c0 for permissions */\n        if (f) {\n            f->flags |= FL_RDWR;\n            if (f && f->owner && f->owner->ops.open) {\n                if ((O_MODE(flags) != O_RDONLY) && ((f->flags & FL_WRONLY)== 0))\n                    return -EPERM;\n                ret = f->owner->ops.open(path, flags);\n                if (ret >= 0) {\n                    task_fd_setmask(ret, flags);\n                    task_fd_set_flags(ret, flags);\n                    task_fd_set_off(f, 0);\n                }\n                return ret;\n            }\n        }\n    }\n    if (f == NULL)\n       return -ENOENT;\n    if (f->flags & FL_INUSE)\n        return -EBUSY;\n    if (f->flags & FL_DIR)\n        return -EISDIR;\n    ret = task_filedesc_add(f);\n    task_fd_setmask(ret, flags);\n    task_fd_set_flags(ret,flags);\n    task_fd_set_off(f, 0);\n    if (flags & O_APPEND)\n        task_fd_set_off(f, f->size); \n    return ret;\n}\n\nint sys_close_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    struct fnode *f = task_filedesc_get(arg1);\n    if (f != NULL) {\n        if (f->owner->ops.close) {\n            f->owner->ops.close(f);\n        }\n        task_filedesc_del(arg1);\n        return 0;\n    }\n    return -EINVAL;\n}\n\nint sys_seek_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    struct fnode *fno = task_filedesc_get(arg1);\n    if (!fno)\n        return -EINVAL;\n    if (fno->owner->ops.seek) {\n        return fno->owner->ops.seek(fno, arg2, arg3);\n    } else return -EOPNOTSUPP;\n}\n\nint sys_ioctl_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    struct fnode *fno = task_filedesc_get(arg1);\n    if (!fno)\n        return -EINVAL;\n    if (fno->owner->ops.ioctl) {\n        fno->owner->ops.ioctl(fno, (uint32_t)arg2, (void *)arg3);\n    } else return -EOPNOTSUPP;\n}\n\nint sys_link_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    struct fnode *fno;\n    if (task_ptr_valid((void*)arg1) || task_ptr_valid((void*)arg2))\n        return -EACCES;\n    fno = fno_link((char*)arg1, (char *)arg2);\n    if (fno)\n        return 0;\n    else return -EINVAL;\n}\n\n\nint sys_mkdir_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    char *path = (char *)arg1;\n    char abs_p[MAX_FILE];\n    struct fnode *f;\n    if (task_ptr_valid(path))\n        return -EACCES;\n    path_abs(path, abs_p, MAX_FILE);\n    if (fno_create_dir(abs_p, arg2))\n        return 0;\n    return -ENOENT;\n}\n\nint sys_unlink_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    char *path = (char *)arg1;\n    char abs_p[MAX_FILE];\n    struct fnode *f;\n    if (task_ptr_valid(path))\n        return -EACCES;\n    path_abs(path, abs_p, MAX_FILE);\n    f = fno_search_nofollow(abs_p); /* Don't follow symlink */\n    if (f) {\n        fno_unlink(f);\n        return 0;\n    }\n    return -ENOENT;\n}\n\nint sys_opendir_hdlr(uint32_t arg1)\n{\n    struct fnode *fno;\n    if (task_ptr_valid((void*)arg1))\n        return -EACCES;\n    fno = fno_search((char *)arg1);\n    if (fno && (fno->flags & FL_DIR)) {\n        if (fno->flags & FL_INUSE)\n            return (int)NULL; /* XXX EBUSY */\n        /* Use .off to store current readdir ptr */\n        fno->dir_ptr = (int)fno->children;\n        fno->flags |= FL_INUSE;\n        return (int)fno;\n    } else {\n        return (int)NULL;\n    }\n}\n\nint sys_readdir_hdlr(uint32_t arg1, uint32_t arg2)\n{\n    struct fnode *fno;\n    struct fnode *next;\n    struct dirent *ep;\n\n    fno = (struct fnode *)arg1;\n    ep = (struct dirent *)arg2;\n    if (task_ptr_valid(ep))\n       return  -EACCES;\n\n    next = (struct fnode *)fno->dir_ptr;\n    if (!fno || !ep)\n        return -ENOENT;\n    if (!next) {\n        return -1;\n    }\n    fno->dir_ptr = (int)next->next;\n    ep->d_ino = 0; /* TODO: populate with inode? */\n    strncpy(ep->d_name, next->fname, 256);\n    return 0;\n}\n\nint sys_closedir_hdlr(uint32_t arg1)\n{\n    struct fnode *fno = (struct fnode *)arg1;\n    fno->dir_ptr = 0;\n    fno->flags &= ~(FL_INUSE);\n    return 0;\n}\n\n\nstatic int stat_hdlr(char *path, struct stat *st)\n{\n    char abs_p[MAX_FILE];\n    struct fnode *fno;\n    path_abs(path, abs_p, MAX_FILE);\n    fno = fno_search_nofollow(abs_p);\n    if (!fno)\n        return -ENOENT;\n    if (fno->flags & FL_DIR) {\n        st->st_mode = S_IFDIR;\n        st->st_size = 0;\n    } else if (fno->flags & FL_TTY) {\n        st->st_mode = S_IFCHR;\n        st->st_size = 0;\n    } else if (fno->flags & FL_BLK) {\n        st->st_mode = S_IFBLK;\n        st->st_size = 0;\n    } else if (fno->flags & FL_LINK) {\n        return stat_hdlr(fno->linkname, st); /* Stat follows symlink */\n    } else {\n        st->st_mode = S_IFREG;\n        st->st_size = fno->size;\n    }\n\n    if (fno->flags & FL_EXEC) {\n        st->st_mode |= P_EXEC;\n    }\n    return 0;\n}\n\nint sys_stat_hdlr(char *arg1, struct stat *arg2)\n{\n    char *path = arg1;\n    struct stat *st = arg2;\n    if (task_ptr_valid(path) || task_ptr_valid(st))\n       return  -EACCES;\n    return stat_hdlr(path, st);\n}\n\nint sys_fstat_hdlr(uint32_t arg1, struct stat *arg2)\n{\n    struct stat *st = arg2;\n    struct fnode *fno = task_filedesc_get(arg1);\n    if (!fno)\n        return -ENOENT;\n    if (task_ptr_valid(st))\n       return  -EACCES;\n    if (fno->flags & FL_DIR) {\n        st->st_mode = S_IFDIR;\n        st->st_size = 0;\n    } else if (fno->flags & FL_LINK) {\n        return stat_hdlr(fno->linkname, st); /* Stat follows symlink */\n    } else {\n        st->st_mode = S_IFREG;\n        st->st_size = fno->size;\n    }\n\n    if (fno->flags & FL_EXEC) {\n        st->st_mode |= P_EXEC;\n    }\n    return 0;\n}\n\nint sys_lstat_hdlr(char *arg1, struct stat *arg2)\n{\n    char *path = arg1;\n    struct stat *st = arg2;\n    char abs_p[MAX_FILE];\n    struct fnode *fno;\n    if (task_ptr_valid(st) || task_ptr_valid(path))\n       return  -EACCES;\n    path_abs(path, abs_p, MAX_FILE);\n    fno = fno_search_nofollow(abs_p);\n    if (!fno)\n        return -ENOENT;\n    if (fno->flags & FL_DIR) {\n        st->st_mode = S_IFDIR;\n        st->st_size = 0;\n    } else if (fno->flags & FL_TTY) {\n        st->st_mode = S_IFCHR;\n        st->st_size = 0;\n    } else if (fno->flags & FL_BLK) {\n        st->st_mode = S_IFBLK;\n        st->st_size = 0;\n    } else if (fno->flags & FL_LINK) {\n        st->st_mode = S_IFLNK; /* lstat gives info about the link itself */\n        st->st_size = 0;\n    } else {\n        st->st_mode = S_IFREG;\n        st->st_size = fno->size;\n    }\n\n    if (fno->flags & FL_EXEC) {\n        st->st_mode |= P_EXEC;\n    }\n    return 0;\n}\n\nint vfs_truncate(struct fnode *fno, unsigned size)\n{\n    if (!fno)\n        return -ENOENT;\n    if ((fno->flags & FL_WRONLY) == 0)\n        return -EPERM;\n    if (!fno->owner ||  !fno->owner->ops.truncate)\n        return -EOPNOTSUPP;\n    return fno->owner->ops.truncate(fno, size);\n}\n\nint sys_ftruncate_hdlr(uint32_t arg1, unsigned arg2)\n{\n    struct fnode *fno = task_filedesc_get(arg1);\n    return vfs_truncate(fno, arg2);\n}\n\nint sys_truncate_hdlr(char *arg1, unsigned arg2)\n{\n    char abs_p[MAX_FILE];\n    struct fnode *fno;\n    if (task_ptr_valid((void*)arg1))\n        return -EACCES;\n    path_abs(arg1, abs_p, MAX_FILE);\n    fno = fno_search(abs_p);\n    return vfs_truncate(fno, arg2);\n}\n\nint sys_chdir_hdlr(char *arg1)\n{\n    char *path = arg1;\n    char abs_p[MAX_FILE];\n    struct fnode *f;\n    if (task_ptr_valid(path))\n       return  -EACCES;\n    path_abs(path, abs_p, MAX_FILE);\n\n    f = fno_search(abs_p);\n    if (!f || (!(f->flags & FL_DIR)))\n        return -ENOTDIR;\n    task_chdir(f);\n    return 0;\n}\n\nint sys_isatty_hdlr(uint32_t arg1)\n{\n    struct fnode *f = task_filedesc_get(arg1);\n    if (f && f->flags & FL_TTY)\n        return 1;\n    return 0;\n}\n\nint sys_ttyname_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3)\n{\n    struct fnode *f = task_filedesc_get(arg1);\n    if (task_ptr_valid((void*)arg2))\n       return  -EACCES;\n    if (f && f->flags & FL_TTY) {\n        strncpy((char *)arg2, f->fname, arg3);\n        return 0;\n    }\n    return -EBADF;\n}\n\nint sys_getcwd_hdlr(uint32_t arg1, uint32_t arg2)\n{\n    char *path = (char *)arg1;\n    int len = (int)arg2;\n    if (task_ptr_valid(path))\n       return  -EACCES;\n    if (fno_fullpath(task_getcwd(), path, len) > 0)\n        return arg1;\n    return 0;\n}\n\nvoid __attribute__((weak)) devnull_init(struct fnode *dev)\n{\n\n}\n\nvoid __attribute__((weak)) memfs_init(void)\n{\n\n}\n\nvoid __attribute__((weak)) xipfs_init(void)\n{\n\n}\n\nvoid __attribute__((weak)) sysfs_init(void)\n{\n\n}\n\nvoid __attribute__((weak)) fatfs_init(void)\n{\n\n}\n\nvoid __attribute__((weak)) devgpio_init(struct fnode *dev)\n{\n\n}\n\n\nvoid __attribute__((weak)) devuart_init(struct fnode *dev)\n{\n\n}\n\nvoid __attribute__((weak)) devspi_init(struct fnode *dev)\n{\n\n}\n\nint vfs_mount(char *source, char *target, char *module, uint32_t flags, void *args)\n{\n    struct module *m;\n    if (!module || !target)\n        return -ENOMEDIUM;\n    m = module_search(module);\n    if (!m || !m->mount)\n        return -EOPNOTSUPP;\n    if (m->mount(source, target, flags, args) == 0) {\n        struct mountpoint *mp = kalloc(sizeof(struct mountpoint));\n        if (mp) {\n            mp->target = fno_search(target);\n            mp->next = MTAB;\n            MTAB = mp;\n        }\n        return 0;\n    }\n    return -ENOENT;\n}\n\nint vfs_umount(char *target, uint32_t flags)\n{\n    struct fnode *f;\n    int ret;\n    struct mountpoint *mp = MTAB, *prev = NULL;\n    if (!target)\n        return -ENOENT;\n    f = fno_search(target);\n    if (!f || !f->owner || !f->owner->umount)\n        return -ENOMEDIUM;\n    ret = f->owner->umount(target, flags);\n    if (ret < 0)\n        return ret;\n\n    while (mp) {\n        if (mp->target == f) {\n            if (!prev) {\n                MTAB = mp->next;\n                break;\n            } else {\n                prev->next = mp;\n\n            }\n            kfree(mp);\n        }\n        prev = mp;\n        mp = mp->next;\n    }\n    return 0;\n}\n\nint sys_mount_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    char *source = (char *)arg1;\n    char *target = (char *)arg2;\n    char *module = (char *)arg3;\n    uint32_t flags = arg4;\n    void *args = (void*)arg5;\n    if (task_ptr_valid((void*)arg1) || task_ptr_valid((void*)arg2)|| task_ptr_valid((void*)arg3)|| (arg5 && task_ptr_valid((void*)arg5)))\n       return  -EACCES;\n    return vfs_mount(source, target, module, flags, args);\n}\n\nint sys_umount_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5)\n{\n    if (task_ptr_valid((void*)arg1))\n        return -EACCES;\n    char *target = (char *)arg1;\n    uint32_t flags = arg2;\n    return vfs_umount(target, flags);\n\n}\n\nint sys_fcntl_hdlr(uint32_t arg1, uint32_t arg2, uint32_t arg3)\n{\n    int fd = arg1;\n    int cmd = arg2;\n    uint32_t fl_set = arg3;\n    struct fnode *f = task_filedesc_get(arg1);\n    if (!f) {\n        return -EINVAL;\n    }\n    if (cmd == F_SETFL) {\n        f->flags |= fl_set;\n    } else if (cmd == F_GETFL) {\n        return f->flags;\n    }\n    return 0;\n}\n\nvoid vfs_init(void)\n{\n    struct fnode *dev = NULL;\n    /* Initialize \"/\" */\n    FNO_ROOT.owner = NULL;\n    FNO_ROOT.fname = \"/\";\n    FNO_ROOT.parent = &FNO_ROOT;\n    FNO_ROOT.children = NULL;\n    FNO_ROOT.next = NULL ;\n    FNO_ROOT.flags = FL_DIR | FL_RDWR;\n\n    /* Init \"/dev\" dir */\n    fno_mkdir(NULL, \"dev\", NULL);\n\n    /* Init \"/sys\" dir */\n    fno_mkdir(NULL, \"sys\", NULL);\n\n    /* Init \"/tmp\" dir */\n    fno_mkdir(NULL, \"tmp\", NULL);\n\n    /* Init \"/bin\" dir */\n    fno_mkdir(NULL, \"bin\", NULL);\n\n    /* Init \"/mnt\" dir */\n    fno_mkdir(NULL, \"mnt\", NULL);\n}\n\n"
  },
  {
    "path": "kernel/vfs.h",
    "content": "#ifndef INC_VFS\n#define INC_VFS\n\n\n#define VFS_TYPE_BIN  (0) /* flat binary */\n#define VFS_TYPE_BFLT (1) /* bFLT binary */\n\nstruct vfs_info {\n    int type;\n    int pic;\n    void (*init)(void *);\n    void * allocated;\n    uint32_t text_size;\n    uint32_t data_size;\n};\n\n\n#endif /* INC_VFS */\n"
  },
  {
    "path": "qemu.gdbinit",
    "content": " tar ext :3333\n layout src\n file kernel.elf\n stepi\n focus c\n"
  },
  {
    "path": "rules/arch.mk",
    "content": "\n###### STACK SIZE #######\nifeq ($(TASK_STACK_SIZE_1K),y)\n    TASK_STACK_SIZE=1024\nendif\nifeq ($(TASK_STACK_SIZE_2K),y)\n    TASK_STACK_SIZE=2048\nendif\nifeq ($(TASK_STACK_SIZE_4K),y)\n    TASK_STACK_SIZE=4096\nendif\nifeq ($(TASK_STACK_SIZE_8K),y)\n    TASK_STACK_SIZE=8192\nendif\n\n#########################\n#Target flags\nCROSS_COMPILE?=arm-frosted-eabi-\nCC:=$(CROSS_COMPILE)gcc\nAS:=$(CROSS_COMPILE)as\nAR:=$(CROSS_COMPILE)ar\nCFLAGS+=-mthumb -mlittle-endian -mthumb-interwork -DCORE_M3 -fno-builtin -ffreestanding -DSYS_CLOCK=$(SYS_CLOCK) -DCORTEX_M3 -DFROSTED\nCFLAGS+=-Ikernel/unicore-mx/include -Ikernel -Iinclude -Ikernel/drivers -I. -Ikernel/frosted-headers/include\nPREFIX:=$(PWD)/build\nLDFLAGS:=-Wl,-gc-sections -nostartfiles -L$(PREFIX)/lib \nCFLAGS+=-mthumb -mlittle-endian -mthumb-interwork\nCFLAGS+=-DCORE_M3 -DBOARD_$(BOARD) -D$(ARCH) -mcpu=$(MCPU)\nCFLAGS+=-DCONFIG_KMEM_SIZE=$(KMEM_SIZE)\nCFLAGS+=-DCONFIG_TASK_STACK_SIZE=$(TASK_STACK_SIZE)\n\n# KERNEL DEBUG\nCFLAGS-$(KLOG)+=-DCONFIG_KLOG\nCFLAGS+=-DCONFIG_KLOG_SIZE=$(KLOG_SIZE)\nCFLAGS-$(HARDFAULT_DBG)+=-DCONFIG_HARDFAULT_DBG\nCFLAGS-$(MEMFAULT_DBG)+=-DCONFIG_EXTENDED_MEMFAULT\nCFLAGS-$(STRACE)+=-DCONFIG_SYSCALL_TRACE\n\n#PTHREADS\nCFLAGS-$(PTHREADS)+=-DCONFIG_PTHREADS\n\n# IPC\nCFLAGS-$(PIPE)+=-DCONFIG_PIPE\nCFLAGS-$(SIGNALS)+=-DCONFIG_SIGNALS\n\n#MPU\nCFLAGS-$(MPU)+=-DCONFIG_MPU\n\n#GCC Optimizations\nCFLAGS-$(GDB_CFLAG)+=-ggdb3\nCFLAGS-$(OPTIMIZE_NONE)+=-O0\nCFLAGS-$(OPTIMIZE_SIZE)+=-Os\nCFLAGS-$(OPTIMIZE_PERF)+=-O3\n\nCFLAGS+=$(CFLAGS-y)\n#Include paths\nCFLAGS+=-Ikernel -Iinclude -I. -Ikernel/unicore-mx/include/unicore-mx -Ikernel/unicore-mx/include\n#Freestanding options\nCFLAGS+=-fno-builtin\nCFLAGS+=-ffreestanding\nCFLAGS+=-nostdlib\nASFLAGS+=-mthumb -mlittle-endian -mthumb-interwork -ggdb -mcpu=$(MCPU)\n\n"
  },
  {
    "path": "rules/config.mk",
    "content": "#Common code used to read the .config\nRAM1_SIZE=0  #KiB\nRAM2_SIZE=0  #KiB\nRAM3_SIZE=0  #KiB\nSDRAM_SIZE=0 #B\n\nifeq ($(RAM_SIZE_368KB),y)\n\tRAM1_SIZE=368\nendif\nifeq ($(RAM_SIZE_320KB),y)\n\tRAM1_SIZE=320\nendif\nifeq ($(RAM_SIZE_256KB),y)\n\tRAM1_SIZE=256\nendif\nifeq ($(RAM_SIZE_192KB),y)\n\tRAM1_SIZE=192\nendif\nifeq ($(RAM_SIZE_128KB),y)\n\tRAM1_SIZE=128\nendif\nifeq ($(RAM_SIZE_96KB),y)\n\tRAM1_SIZE=96\nendif\nifeq ($(RAM_SIZE_64KB),y)\n\tRAM1_SIZE=64\nendif\nifeq ($(RAM_SIZE_32KB),y)\n\tRAM1_SIZE=32\nendif\nifeq ($(RAM_SIZE_24KB),y)\n\tRAM1_SIZE=24\nendif\nifeq ($(RAM_SIZE_16KB),y)\n\tRAM1_SIZE=16\nendif\n\nifeq ($(ARCH_LPC17XX),y)\n\tCPU=cortex-m\n\tBOARD=lpc17xx\n\tFLASH_ORIGIN=0x00000000\n\tRAM1_BASE=0x10000000\n\tRAM2_BASE=0x2007C000\n\tRAM3_BASE=0x20080000\n\tRAM2_SIZE=16\n\tRAM3_SIZE=16\n\tARCH=LPC17XX\n\tMCPU=cortex-m3\n\tCFLAGS+=-DLPC17XX -DCONFIG_SRAM_EXTRA\n\tUNICOREMX_TARGET=lpc17xx\nendif\n\nifeq ($(ARCH_LM3S),y)\n\tCPU=cortex-m\n\tBOARD=lm3s\n\tFLASH_ORIGIN=0x00000000\n\tRAM1_BASE=0x20000000\n\tSYS_CLOCK=50000000\n\tARCH=LM3S\n\tCFLAGS+=-DLM3S\n\tMCPU=cortex-m3\n\tUNICOREMX_TARGET=lm3s\nendif\n\nifeq ($(ARCH_NRF51),y)\n\tCPU=cortex-m\n\tBOARD=nrf51\n\tFLASH_ORIGIN=0x00000000\n\tRAM1_BASE=0x20000000\n\tRAM1_SIZE=32\n\tSYS_CLOCK=16000000\n\tARCH=NRF51\n\tMCPU=cortex-m0\n\tCFLAGS+=-DNRF51 -lgcc -DCUSTOM_SYSTICK\n\tUNICOREMX_TARGET=nrf/51\nendif\n\n\nifeq ($(ARCH_NRF52),y)\n\tCPU=cortex-m\n\tBOARD=nrf52\n\tFLASH_ORIGIN=0x00000000\n\tRAM1_BASE=0x20000000\n\tRAM1_SIZE=64\n\tSYS_CLOCK=84000000\n\tARCH=NRF52\n\tMCPU=cortex-m4\n\tCFLAGS+=-DNRF52\n\tUNICOREMX_TARGET=nrf/52\nendif\n\n\nifeq ($(ARCH_STM32F4),y)\n\tCPU=cortex-m\n\tBOARD=stm32f4\n\tFLASH_ORIGIN=0x08000000\n\tRAM1_BASE=0x20000000\n\tRAM1_SIZE=128\n\tRAM2_BASE=0x10000000\n\tRAM2_SIZE=64\n\tSDRAM_BASE=0xD0000000\n\tSDRAM_SIZE=0x800000\n\tCFLAGS+=-DSTM32F4 -mfloat-abi=soft -DCONFIG_SRAM_EXTRA\n\tMCPU=cortex-m4\n\tARCH=STM32F4\n\tOPENCM3FLAGS=FP_FLAGS=\"-mfloat-abi=soft\"\n\tUNICOREMX_TARGET=stm32/f4\nendif\n\nifeq ($(ARCH_STM32F7),y)\n\tCPU=cortex-m\n\tBOARD=stm32f7\n\tFLASH_ORIGIN=0x08000000\n\tRAM1_BASE=0x20000000\n\tSDRAM_BASE=0xC0000000\n\tSDRAM_SIZE=0x800000\n\tCFLAGS+=-DSTM32F7 -mfloat-abi=soft -DCONFIG_SRAM_EXTRA\n\tMCPU=cortex-m4\n\tARCH=STM32F7\n\tOPENCM3FLAGS=FP_FLAGS=\"-mfloat-abi=soft\"\n\tUNICOREMX_TARGET=stm32/f7\nendif\n\nifeq ($(MACH_STM32F405Pyboard),y)\n\tCFLAGS+=-DPYBOARD\nendif\n\nifeq ($(MACH_STM32F429Discovery),y)\n\tCFLAGS+=-DF429DISCO\nendif\n\nifeq ($(FLASH_SIZE_2MB),y)\n\tFLASH_SIZE=2048\nendif\nifeq ($(FLASH_SIZE_1MB),y)\n\tFLASH_SIZE=1024\nendif\nifeq ($(FLASH_SIZE_512KB),y)\n\tFLASH_SIZE=512\nendif\nifeq ($(FLASH_SIZE_384KB),y)\n\tFLASH_SIZE=384\nendif\nifeq ($(FLASH_SIZE_256KB),y)\n\tFLASH_SIZE=256\nendif\nifeq ($(FLASH_SIZE_192KB),y)\n\tFLASH_SIZE=192\nendif\nifeq ($(FLASH_SIZE_128KB),y)\n\tFLASH_SIZE=128\nendif\n\nifeq ($(CLK_48MHZ),y)\n\tSYS_CLOCK=48000000\nendif\nifeq ($(CLK_84MHZ),y)\n\tSYS_CLOCK=84000000\nendif\nifeq ($(CLK_100MHZ),y)\n\tSYS_CLOCK=100000000\nendif\nifeq ($(CLK_120MHZ),y)\n\tSYS_CLOCK=120000000\nendif\nifeq ($(CLK_168MHZ),y)\n\tSYS_CLOCK=168000000\nendif\nifeq ($(CLK_180MHZ),y)\n\tSYS_CLOCK=180000000\nendif\nifeq ($(CLK_216MHZ),y)\n        SYS_CLOCK=216000000\nendif\n#USARTs\nifeq ($(USART_0),y)\n    CFLAGS+=-DCONFIG_USART_0\nendif\nifeq ($(USART_1),y)\n    CFLAGS+=-DCONFIG_USART_1\nendif\nifeq ($(USART_2),y)\n    CFLAGS+=-DCONFIG_USART_2\nendif\nifeq ($(USART_3),y)\n    CFLAGS+=-DCONFIG_USART_3\nendif\nifeq ($(USART_4),y)\n    CFLAGS+=-DCONFIG_USART_4\nendif\nifeq ($(USART_6),y)\n    CFLAGS+=-DCONFIG_USART_6\nendif\n#UARTs\nifeq ($(UART_0),y)\n    CFLAGS+=-DCONFIG_UART_0\nendif\nifeq ($(UART_1),y)\n    CFLAGS+=-DCONFIG_UART_1\nendif\nifeq ($(UART_2),y)\n    CFLAGS+=-DCONFIG_UART_2\nendif\nifeq ($(UART_3),y)\n    CFLAGS+=-DCONFIG_UART_3\nendif\nifeq ($(UART_4),y)\n    CFLAGS+=-DCONFIG_UART_4\nendif\n\n#SPIs\nifeq ($(SPI_1),y)\n    CFLAGS+=-DCONFIG_SPI_1\nendif\nifeq ($(SPI_2),y)\n    CFLAGS+=-DCONFIG_SPI_2\nendif\nifeq ($(SPI_3),y)\n    CFLAGS+=-DCONFIG_SPI_3\nendif\nifeq ($(SPI_4),y)\n    CFLAGS+=-DCONFIG_SPI_4\nendif\nifeq ($(SPI_5),y)\n    CFLAGS+=-DCONFIG_SPI_5\nendif\nifeq ($(SPI_6),y)\n    CFLAGS+=-DCONFIG_SPI_6\nendif\n\n#RNG\nifeq ($(DEVRNG),y)\n    CFLAGS+=-DCONFIG_RNG\nendif\n\n#FRAND\nifeq ($(DEVFRAND),y)\n    CFLAGS+=-DCONFIG_FRAND\nendif\n\n\n#I2Cs\nifeq ($(I2C1),y)\n    CFLAGS+=-DCONFIG_I2C1\nendif\nifeq ($(I2C2),y)\n    CFLAGS+=-DCONFIG_I2C2\nendif\nifeq ($(I2C3),y)\n    CFLAGS+=-DCONFIG_I2C3\nendif\n\n\n#LOWPOWER\nifeq ($(LOWPOWER),y)\n  CFLAGS+=-DCONFIG_LOWPOWER\nendif\n#PICOTCP\nifeq ($(PICOTCP),y)\n  CFLAGS+=-DCONFIG_PICOTCP\nendif\n\n\nAPPS_ORIGIN=$$(( $(KFLASHMEM_SIZE) * 1024))\nCFLAGS+=-DFLASH_ORIGIN=$(FLASH_ORIGIN)\nCFLAGS+=-DAPPS_ORIGIN=$(APPS_ORIGIN)\nCFLAGS+=-DCONFIG_KRAM_SIZE=$(KRAMMEM_SIZE)\nCFLAGS+=-DCONFIG_SYS_CLOCK=$(SYS_CLOCK)\n\n"
  },
  {
    "path": "rules/picotcp.mk",
    "content": "\nifeq ($(TCPIP_MEMPOOL_YN),y)\n  MEMPOOL+=-DCONFIG_TCPIP_MEMPOOL=$(CONFIG_TCPIP_MEMPOOL)\nendif\n\nifeq ($(PICOTCP),y)\n\tCFLAGS+=-DCONFIG_PICOTCP -I$(PREFIX)/include -Ikernel/net/socket -nostdlib\n    PICO_OPTIONS=CROSS_COMPILE=arm-frosted-eabi- ARCH=cortexm3 RTOS=1 PREFIX=$(PREFIX) \\\n    \t\t DHCP_CLIENT=0 DHCP_SERVER=0 MDNS=0 DNS_SD=0 \\\n    \t\t\t OLSR=0 SLAACV4=0 SNTP_CLIENT=0 PPP=0 TFTP=0 \\\n\t\t\t\t AODV=0 \\\n\t\t\t\t SIXLOWPAN=0 \n    PICO_LIB:=$(PREFIX)/lib/libpicotcp.a\n\nifneq ($(CONFIG_PICOTCP_DEBUG),y)\n  PICO_OPTIONS+=DEBUG=0\nendif\nifneq ($(CONFIG_PICOTCP_LOOP),y)\n  PICO_OPTIONS+=DEVLOOP=0\nendif\nifneq ($(CONFIG_PICOTCP_IPV6),y)\n  PICO_OPTIONS+=IPV6=0\nelse\n  CFLAGS-y:=CONFIG_IPV6=1\nendif\nifneq ($(CONFIG_PICOTCP_IPV4),y)\n  PICO_OPTIONS+=IPV4=0\nendif\nifneq ($(CONFIG_PICOTCP_TCP),y)\n  PICO_OPTIONS+=TCP=0\nendif\nifneq ($(CONFIG_PICOTCP_UDP),y)\n  PICO_OPTIONS+=UDP=0\nendif\nifneq ($(CONFIG_PICOTCP_DNS),y)\n  PICO_OPTIONS+=DNS_CLIENT=0\nelse\n  CFLAGS-$(PICOTCP)+=-DCONFIG_DNS_CLIENT=1\nendif\nifneq ($(CONFIG_PICOTCP_MCAST),y)\n  PICO_OPTIONS+=MCAST=0\nendif\nifneq ($(CONFIG_PICOTCP_NAT),y)\n  PICO_OPTIONS+=NAT=0\nendif\nifneq ($(CONFIG_PICOTCP_IPFILTER),y)\n  PICO_OPTIONS+=IPFILTER=0\nendif\nifeq ($(LOWPOWER),y)\n  PICO_OPTIONS+=TICKLESS=1\nendif\n\n  PICO_OPTIONS+=EXTRA_CFLAGS=\"-DFROSTED -I$(PWD)/kernel -I$(PWD)/include -nostdlib -DPICO_PORT_CUSTOM $(MEMPOOL)\"\n  BUILD_PICO=make -C kernel/net/picotcp $(PICO_OPTIONS)\nendif\n\n"
  },
  {
    "path": "rules/userspace.mk",
    "content": "USERSPACE=frosted-userland\n"
  },
  {
    "path": "scripts/frosted-dev-setup",
    "content": "#!/usr/bin/env bash\n\nprintf \"\\nSetting up Frosted dev env...\";\npath=\"$(pwd)\";\n\ncd ~;\n\nmkdir frosted-dev;\ncd frosted-dev;\n\nsudo apt-get install build-essential cmake libusb-1.0 libusb-1.0.0-dev git screen\n\nwget http://archive.trexotech.com:8081/arm-frosted-eabi-latest.tar.bz2;\ntar xjf arm-frosted-eabi-latest.tar.bz2;\nexport PATH=\"$(pwd)/arm-frosted-eabi/bin:$PATH\";\n\ngit clone https://github.com/texane/stlink.git;\ncd stlink;\nmkdir build;\ncd build;\ncmake -DCMAKE_BUILD_TYPE=Debug ..;\nmake;\ncd ..;\nsudo cp etc/udev/rules.d/*.rules /etc/udev/rules.d/;\nsudo udevadm control --reload-rules;\nsudo udevadm trigger;\nexport PATH=\"$(pwd)/build:$PATH\";\n\ncd \"$path\";\n\ngit submodule init;\ngit submodule update;\ncd frosted-userland;\ngit submodule init;\ngit submodule update;\n\n\nprintf \" OK!\\n\\nFrosted dev env setup in ~/frosted-dev\\n\\n\";\n"
  },
  {
    "path": "scripts/frosted-qemu-setup",
    "content": "#!/usr/bin/env bash\n\n\nif [[ $- != *i* ]]; then\n    echo \"You should dot me in\" >&2;\n    exit 1;\nfi\n\nprintf \"\\nSetting up Frosted qemu env...\\n\\n\";\npath=\"$(pwd)\";\n\ncd ~;\n\nmkdir frosted-qemu\ncd frosted-qemu;\n\nsudo apt-get install build-essential cmake libusb-1.0 libusb-1.0.0-dev git screen;\n\nwget http://archive.trexotech.com:8081/arm-frosted-eabi-latest.tar.bz2;\ntar xjf arm-frosted-eabi-latest.tar.bz2;\nexport PATH=\"$(pwd)/arm-frosted-eabi/bin:$PATH\";\n\nsudo apt-get build-dep qemu;\ngit clone git://github.com/insane-adding-machines/qemu.git;\ncd qemu;\n./configure --prefix=\"$(pwd)/../qemu-bin\" --target-list=arm-softmmu;\nmake;\nsudo make install;\nsudo chmod u+s \"$(pwd)/../qemu-bin/libexec/qemu-bridge-helper\";\n\ncd ..;\nexport PATH=\"$(pwd)/qemu-bin/bin:$PATH\";\n\nsudo mkdir qemu-bin/etc;\nsudo mkdir qemu-bin/etc/qemu;\nprintf \"allow br0\\n\" | sudo tee qemu-bin/etc/qemu/bridge.conf;\n\ncd \"$path\";\n\ngit submodule init;\ngit submodule update;\ncd frosted-userland;\ngit submodule init;\ngit submodule update;\ncd ..;\n\nprintf \"\\nFrosted qemu env setup in ~/frosted-qemu\\n\\n\";\n\nprintf \"For adding the env path autmatically, update your PATH with:\\n\";\nprintf \"$HOME/frosted-qemu/arm-frosted-eabi/bin\\n\";\nprintf \"$HOME/frosted-qemu/qemu-bin/bin\\n\\n\";\n"
  },
  {
    "path": "xipfs.h",
    "content": "#ifndef XIPFS_NULL\n#define XIPFS_NULL\n\nvoid xipfs_init(void);\n\n#endif\n\n"
  }
]