├── .gitignore ├── LICENSE ├── README.md └── genimage ├── .gitignore ├── Makefile ├── crc32.h ├── dumpimage.c ├── fmh.h ├── fmh.py ├── fmhcore.c ├── fwinfo.c ├── genimage.c ├── iniparser-2.14 ├── LICENSE ├── Makefile └── src │ ├── dictionary.c │ ├── dictionary.h │ ├── iniparser.c │ ├── iniparser.h │ ├── strlib.c │ └── strlib.h └── renew-ima.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.o 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | 60 | Finally, software patents pose a constant threat to the existence of 61 | any free program. We wish to make sure that a company cannot 62 | effectively restrict the users of a free program by obtaining a 63 | restrictive license from a patent holder. Therefore, we insist that 64 | any patent license obtained for a version of the library must be 65 | consistent with the full freedom of use specified in this license. 66 | 67 | Most GNU software, including some libraries, is covered by the 68 | ordinary GNU General Public License. This license, the GNU Lesser 69 | General Public License, applies to certain designated libraries, and 70 | is quite different from the ordinary General Public License. We use 71 | this license for certain libraries in order to permit linking those 72 | libraries into non-free programs. 73 | 74 | When a program is linked with a library, whether statically or using 75 | a shared library, the combination of the two is legally speaking a 76 | combined work, a derivative of the original library. The ordinary 77 | General Public License therefore permits such linking only if the 78 | entire combination fits its criteria of freedom. The Lesser General 79 | Public License permits more lax criteria for linking other code with 80 | the library. 81 | 82 | We call this license the "Lesser" General Public License because it 83 | does Less to protect the user's freedom than the ordinary General 84 | Public License. It also provides other free software developers Less 85 | of an advantage over competing non-free programs. These disadvantages 86 | are the reason we use the ordinary General Public License for many 87 | libraries. However, the Lesser license provides advantages in certain 88 | special circumstances. 89 | 90 | For example, on rare occasions, there may be a special need to 91 | encourage the widest possible use of a certain library, so that it becomes 92 | a de-facto standard. To achieve this, non-free programs must be 93 | allowed to use the library. A more frequent case is that a free 94 | library does the same job as widely used non-free libraries. In this 95 | case, there is little to gain by limiting the free library to free 96 | software only, so we use the Lesser General Public License. 97 | 98 | In other cases, permission to use a particular library in non-free 99 | programs enables a greater number of people to use a large body of 100 | free software. For example, permission to use the GNU C Library in 101 | non-free programs enables many more people to use the whole GNU 102 | operating system, as well as its variant, the GNU/Linux operating 103 | system. 104 | 105 | Although the Lesser General Public License is Less protective of the 106 | users' freedom, it does ensure that the user of a program that is 107 | linked with the Library has the freedom and the wherewithal to run 108 | that program using a modified version of the Library. 109 | 110 | The precise terms and conditions for copying, distribution and 111 | modification follow. Pay close attention to the difference between a 112 | "work based on the library" and a "work that uses the library". The 113 | former contains code derived from the library, whereas the latter must 114 | be combined with the library in order to run. 115 | 116 | 117 | GNU LESSER GENERAL PUBLIC LICENSE 118 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 119 | 120 | 0. This License Agreement applies to any software library or other 121 | program which contains a notice placed by the copyright holder or 122 | other authorized party saying it may be distributed under the terms of 123 | this Lesser General Public License (also called "this License"). 124 | Each licensee is addressed as "you". 125 | 126 | A "library" means a collection of software functions and/or data 127 | prepared so as to be conveniently linked with application programs 128 | (which use some of those functions and data) to form executables. 129 | 130 | The "Library", below, refers to any such software library or work 131 | which has been distributed under these terms. A "work based on the 132 | Library" means either the Library or any derivative work under 133 | copyright law: that is to say, a work containing the Library or a 134 | portion of it, either verbatim or with modifications and/or translated 135 | straightforwardly into another language. (Hereinafter, translation is 136 | included without limitation in the term "modification".) 137 | 138 | "Source code" for a work means the preferred form of the work for 139 | making modifications to it. For a library, complete source code means 140 | all the source code for all modules it contains, plus any associated 141 | interface definition files, plus the scripts used to control compilation 142 | and installation of the library. 143 | 144 | Activities other than copying, distribution and modification are not 145 | covered by this License; they are outside its scope. The act of 146 | running a program using the Library is not restricted, and output from 147 | such a program is covered only if its contents constitute a work based 148 | on the Library (independent of the use of the Library in a tool for 149 | writing it). Whether that is true depends on what the Library does 150 | and what the program that uses the Library does. 151 | 152 | 1. You may copy and distribute verbatim copies of the Library's 153 | complete source code as you receive it, in any medium, provided that 154 | you conspicuously and appropriately publish on each copy an 155 | appropriate copyright notice and disclaimer of warranty; keep intact 156 | all the notices that refer to this License and to the absence of any 157 | warranty; and distribute a copy of this License along with the 158 | Library. 159 | 160 | You may charge a fee for the physical act of transferring a copy, 161 | and you may at your option offer warranty protection in exchange for a 162 | fee. 163 | 164 | 165 | 2. You may modify your copy or copies of the Library or any portion 166 | of it, thus forming a work based on the Library, and copy and 167 | distribute such modifications or work under the terms of Section 1 168 | above, provided that you also meet all of these conditions: 169 | 170 | a) The modified work must itself be a software library. 171 | 172 | b) You must cause the files modified to carry prominent notices 173 | stating that you changed the files and the date of any change. 174 | 175 | c) You must cause the whole of the work to be licensed at no 176 | charge to all third parties under the terms of this License. 177 | 178 | d) If a facility in the modified Library refers to a function or a 179 | table of data to be supplied by an application program that uses 180 | the facility, other than as an argument passed when the facility 181 | is invoked, then you must make a good faith effort to ensure that, 182 | in the event an application does not supply such function or 183 | table, the facility still operates, and performs whatever part of 184 | its purpose remains meaningful. 185 | 186 | (For example, a function in a library to compute square roots has 187 | a purpose that is entirely well-defined independent of the 188 | application. Therefore, Subsection 2d requires that any 189 | application-supplied function or table used by this function must 190 | be optional: if the application does not supply it, the square 191 | root function must still compute square roots.) 192 | 193 | These requirements apply to the modified work as a whole. If 194 | identifiable sections of that work are not derived from the Library, 195 | and can be reasonably considered independent and separate works in 196 | themselves, then this License, and its terms, do not apply to those 197 | sections when you distribute them as separate works. But when you 198 | distribute the same sections as part of a whole which is a work based 199 | on the Library, the distribution of the whole must be on the terms of 200 | this License, whose permissions for other licensees extend to the 201 | entire whole, and thus to each and every part regardless of who wrote 202 | it. 203 | 204 | Thus, it is not the intent of this section to claim rights or contest 205 | your rights to work written entirely by you; rather, the intent is to 206 | exercise the right to control the distribution of derivative or 207 | collective works based on the Library. 208 | 209 | In addition, mere aggregation of another work not based on the Library 210 | with the Library (or with a work based on the Library) on a volume of 211 | a storage or distribution medium does not bring the other work under 212 | the scope of this License. 213 | 214 | 3. You may opt to apply the terms of the ordinary GNU General Public 215 | License instead of this License to a given copy of the Library. To do 216 | this, you must alter all the notices that refer to this License, so 217 | that they refer to the ordinary GNU General Public License, version 2, 218 | instead of to this License. (If a newer version than version 2 of the 219 | ordinary GNU General Public License has appeared, then you can specify 220 | that version instead if you wish.) Do not make any other change in 221 | these notices. 222 | 223 | 224 | Once this change is made in a given copy, it is irreversible for 225 | that copy, so the ordinary GNU General Public License applies to all 226 | subsequent copies and derivative works made from that copy. 227 | 228 | This option is useful when you wish to copy part of the code of 229 | the Library into a program that is not a library. 230 | 231 | 4. You may copy and distribute the Library (or a portion or 232 | derivative of it, under Section 2) in object code or executable form 233 | under the terms of Sections 1 and 2 above provided that you accompany 234 | it with the complete corresponding machine-readable source code, which 235 | must be distributed under the terms of Sections 1 and 2 above on a 236 | medium customarily used for software interchange. 237 | 238 | If distribution of object code is made by offering access to copy 239 | from a designated place, then offering equivalent access to copy the 240 | source code from the same place satisfies the requirement to 241 | distribute the source code, even though third parties are not 242 | compelled to copy the source along with the object code. 243 | 244 | 5. A program that contains no derivative of any portion of the 245 | Library, but is designed to work with the Library by being compiled or 246 | linked with it, is called a "work that uses the Library". Such a 247 | work, in isolation, is not a derivative work of the Library, and 248 | therefore falls outside the scope of this License. 249 | 250 | However, linking a "work that uses the Library" with the Library 251 | creates an executable that is a derivative of the Library (because it 252 | contains portions of the Library), rather than a "work that uses the 253 | library". The executable is therefore covered by this License. 254 | Section 6 states terms for distribution of such executables. 255 | 256 | When a "work that uses the Library" uses material from a header file 257 | that is part of the Library, the object code for the work may be a 258 | derivative work of the Library even though the source code is not. 259 | Whether this is true is especially significant if the work can be 260 | linked without the Library, or if the work is itself a library. The 261 | threshold for this to be true is not precisely defined by law. 262 | 263 | If such an object file uses only numerical parameters, data 264 | structure layouts and accessors, and small macros and small inline 265 | functions (ten lines or less in length), then the use of the object 266 | file is unrestricted, regardless of whether it is legally a derivative 267 | work. (Executables containing this object code plus portions of the 268 | Library will still fall under Section 6.) 269 | 270 | Otherwise, if the work is a derivative of the Library, you may 271 | distribute the object code for the work under the terms of Section 6. 272 | Any executables containing that work also fall under Section 6, 273 | whether or not they are linked directly with the Library itself. 274 | 275 | 276 | 6. As an exception to the Sections above, you may also combine or 277 | link a "work that uses the Library" with the Library to produce a 278 | work containing portions of the Library, and distribute that work 279 | under terms of your choice, provided that the terms permit 280 | modification of the work for the customer's own use and reverse 281 | engineering for debugging such modifications. 282 | 283 | You must give prominent notice with each copy of the work that the 284 | Library is used in it and that the Library and its use are covered by 285 | this License. You must supply a copy of this License. If the work 286 | during execution displays copyright notices, you must include the 287 | copyright notice for the Library among them, as well as a reference 288 | directing the user to the copy of this License. Also, you must do one 289 | of these things: 290 | 291 | a) Accompany the work with the complete corresponding 292 | machine-readable source code for the Library including whatever 293 | changes were used in the work (which must be distributed under 294 | Sections 1 and 2 above); and, if the work is an executable linked 295 | with the Library, with the complete machine-readable "work that 296 | uses the Library", as object code and/or source code, so that the 297 | user can modify the Library and then relink to produce a modified 298 | executable containing the modified Library. (It is understood 299 | that the user who changes the contents of definitions files in the 300 | Library will not necessarily be able to recompile the application 301 | to use the modified definitions.) 302 | 303 | b) Use a suitable shared library mechanism for linking with the 304 | Library. A suitable mechanism is one that (1) uses at run time a 305 | copy of the library already present on the user's computer system, 306 | rather than copying library functions into the executable, and (2) 307 | will operate properly with a modified version of the library, if 308 | the user installs one, as long as the modified version is 309 | interface-compatible with the version that the work was made with. 310 | 311 | c) Accompany the work with a written offer, valid for at 312 | least three years, to give the same user the materials 313 | specified in Subsection 6a, above, for a charge no more 314 | than the cost of performing this distribution. 315 | 316 | d) If distribution of the work is made by offering access to copy 317 | from a designated place, offer equivalent access to copy the above 318 | specified materials from the same place. 319 | 320 | e) Verify that the user has already received a copy of these 321 | materials or that you have already sent this user a copy. 322 | 323 | For an executable, the required form of the "work that uses the 324 | Library" must include any data and utility programs needed for 325 | reproducing the executable from it. However, as a special exception, 326 | the materials to be distributed need not include anything that is 327 | normally distributed (in either source or binary form) with the major 328 | components (compiler, kernel, and so on) of the operating system on 329 | which the executable runs, unless that component itself accompanies 330 | the executable. 331 | 332 | It may happen that this requirement contradicts the license 333 | restrictions of other proprietary libraries that do not normally 334 | accompany the operating system. Such a contradiction means you cannot 335 | use both them and the Library together in an executable that you 336 | distribute. 337 | 338 | 339 | 7. You may place library facilities that are a work based on the 340 | Library side-by-side in a single library together with other library 341 | facilities not covered by this License, and distribute such a combined 342 | library, provided that the separate distribution of the work based on 343 | the Library and of the other library facilities is otherwise 344 | permitted, and provided that you do these two things: 345 | 346 | a) Accompany the combined library with a copy of the same work 347 | based on the Library, uncombined with any other library 348 | facilities. This must be distributed under the terms of the 349 | Sections above. 350 | 351 | b) Give prominent notice with the combined library of the fact 352 | that part of it is a work based on the Library, and explaining 353 | where to find the accompanying uncombined form of the same work. 354 | 355 | 8. You may not copy, modify, sublicense, link with, or distribute 356 | the Library except as expressly provided under this License. Any 357 | attempt otherwise to copy, modify, sublicense, link with, or 358 | distribute the Library is void, and will automatically terminate your 359 | rights under this License. However, parties who have received copies, 360 | or rights, from you under this License will not have their licenses 361 | terminated so long as such parties remain in full compliance. 362 | 363 | 9. You are not required to accept this License, since you have not 364 | signed it. However, nothing else grants you permission to modify or 365 | distribute the Library or its derivative works. These actions are 366 | prohibited by law if you do not accept this License. Therefore, by 367 | modifying or distributing the Library (or any work based on the 368 | Library), you indicate your acceptance of this License to do so, and 369 | all its terms and conditions for copying, distributing or modifying 370 | the Library or works based on it. 371 | 372 | 10. Each time you redistribute the Library (or any work based on the 373 | Library), the recipient automatically receives a license from the 374 | original licensor to copy, distribute, link with or modify the Library 375 | subject to these terms and conditions. You may not impose any further 376 | restrictions on the recipients' exercise of the rights granted herein. 377 | You are not responsible for enforcing compliance by third parties with 378 | this License. 379 | 380 | 381 | 11. If, as a consequence of a court judgment or allegation of patent 382 | infringement or for any other reason (not limited to patent issues), 383 | conditions are imposed on you (whether by court order, agreement or 384 | otherwise) that contradict the conditions of this License, they do not 385 | excuse you from the conditions of this License. If you cannot 386 | distribute so as to satisfy simultaneously your obligations under this 387 | License and any other pertinent obligations, then as a consequence you 388 | may not distribute the Library at all. For example, if a patent 389 | license would not permit royalty-free redistribution of the Library by 390 | all those who receive copies directly or indirectly through you, then 391 | the only way you could satisfy both it and this License would be to 392 | refrain entirely from distribution of the Library. 393 | 394 | If any portion of this section is held invalid or unenforceable under any 395 | particular circumstance, the balance of the section is intended to apply, 396 | and the section as a whole is intended to apply in other circumstances. 397 | 398 | It is not the purpose of this section to induce you to infringe any 399 | patents or other property right claims or to contest validity of any 400 | such claims; this section has the sole purpose of protecting the 401 | integrity of the free software distribution system which is 402 | implemented by public license practices. Many people have made 403 | generous contributions to the wide range of software distributed 404 | through that system in reliance on consistent application of that 405 | system; it is up to the author/donor to decide if he or she is willing 406 | to distribute software through any other system and a licensee cannot 407 | impose that choice. 408 | 409 | This section is intended to make thoroughly clear what is believed to 410 | be a consequence of the rest of this License. 411 | 412 | 12. If the distribution and/or use of the Library is restricted in 413 | certain countries either by patents or by copyrighted interfaces, the 414 | original copyright holder who places the Library under this License may add 415 | an explicit geographical distribution limitation excluding those countries, 416 | so that distribution is permitted only in or among countries not thus 417 | excluded. In such case, this License incorporates the limitation as if 418 | written in the body of this License. 419 | 420 | 13. The Free Software Foundation may publish revised and/or new 421 | versions of the Lesser General Public License from time to time. 422 | Such new versions will be similar in spirit to the present version, 423 | but may differ in detail to address new problems or concerns. 424 | 425 | Each version is given a distinguishing version number. If the Library 426 | specifies a version number of this License which applies to it and 427 | "any later version", you have the option of following the terms and 428 | conditions either of that version or of any later version published by 429 | the Free Software Foundation. If the Library does not specify a 430 | license version number, you may choose any version ever published by 431 | the Free Software Foundation. 432 | 433 | 434 | 14. If you wish to incorporate parts of the Library into other free 435 | programs whose distribution conditions are incompatible with these, 436 | write to the author to ask for permission. For software which is 437 | copyrighted by the Free Software Foundation, write to the Free 438 | Software Foundation; we sometimes make exceptions for this. Our 439 | decision will be guided by the two goals of preserving the free status 440 | of all derivatives of our free software and of promoting the sharing 441 | and reuse of software generally. 442 | 443 | NO WARRANTY 444 | 445 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 446 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 447 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 448 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 449 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 450 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 451 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 452 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 453 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 454 | 455 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 456 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 457 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 458 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 459 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 460 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 461 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 462 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 463 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 464 | DAMAGES. 465 | 466 | END OF TERMS AND CONDITIONS 467 | 468 | 469 | How to Apply These Terms to Your New Libraries 470 | 471 | If you develop a new library, and you want it to be of the greatest 472 | possible use to the public, we recommend making it free software that 473 | everyone can redistribute and change. You can do so by permitting 474 | redistribution under these terms (or, alternatively, under the terms of the 475 | ordinary General Public License). 476 | 477 | To apply these terms, attach the following notices to the library. It is 478 | safest to attach them to the start of each source file to most effectively 479 | convey the exclusion of warranty; and each file should have at least the 480 | "copyright" line and a pointer to where the full notice is found. 481 | 482 | 483 | Copyright (C) 484 | 485 | This library is free software; you can redistribute it and/or 486 | modify it under the terms of the GNU Lesser General Public 487 | License as published by the Free Software Foundation; either 488 | version 2.1 of the License, or (at your option) any later version. 489 | 490 | This library is distributed in the hope that it will be useful, 491 | but WITHOUT ANY WARRANTY; without even the implied warranty of 492 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 493 | Lesser General Public License for more details. 494 | 495 | You should have received a copy of the GNU Lesser General Public 496 | License along with this library; if not, write to the Free Software 497 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 498 | 499 | Also add information on how to contact you by electronic and paper mail. 500 | 501 | You should also get your employer (if you work as a programmer) or your 502 | school, if any, to sign a "copyright disclaimer" for the library, if 503 | necessary. Here is a sample; alter the names: 504 | 505 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 506 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 507 | 508 | , 1 April 1990 509 | Ty Coon, President of Vice 510 | 511 | That's all there is to it! 512 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bmc-ami 2 | ======= 3 | 4 | Dump image 5 | ============= 6 | ```sh 7 | $ dumpimage -i FIRMWARE.IMA -o OUTPUT-DIRECTORY 8 | ``` 9 | 10 | Generate image 11 | ============== 12 | From the directory containing "genimage.ini" run: 13 | ```sh 14 | $ genimage 15 | ``` 16 | 17 | u-Boot image 18 | ============ 19 | First check current flags: 20 | ```sh 21 | $ mkimage -l ROOT.bin 22 | Image Name: 23 | Created: Thu Dec 6 23:09:39 2012 24 | Image Type: SuperH Linux RAMDisk Image (uncompressed) 25 | Data Size: 15495168 Bytes = 15132.00 kB = 14.78 MB 26 | Load Address: 00000000 27 | Entry Point: 00000000 28 | ``` 29 | 30 | To re-create u-Boot image (for SuperH arch use "sh"): 31 | ```sh 32 | $ mkimage -A sh -O linux -T ramdisk -C none -d ROOT-new.cramfs ROOT-new.bin 33 | ``` 34 | 35 | Manage the MTD image 36 | ==================== 37 | 1. Expand extracted CONF.bin to the minimal erase block count (8 by 64k, maximum is around 1.5M): 38 | ```$ s=$(stat -c "%s" CONF.bin)``` 39 | ```$ dd if=/dev/zero of=CONF.bin seek=$s bs=1 count=$((0x80000 - $s))``` 40 | 2. Associate /dev/loopX with CONF.bin via losetup: 41 | ```$ losetup /dev/loop0 CONF.bin``` 42 | 3. Associate /dev/loopX with MTD char device (erase size is 64k): 43 | ```$ modprobe block2mtd block2mtd=/dev/loop0,0x10000``` 44 | 4. Insmod MTDBLOCK module to mount image: 45 | ```$ modprobe mtdblock``` 46 | ```$ mount -tjffs2 /dev/mtdblock0 MOUNT_POINT``` 47 | 5. Modify content on your own 48 | 6. Re-create MTD image: 49 | ```sh 50 | $ mkfs.jffs2 -c 12 -l -f -s 0x800 -q -x lzo --pad=0x00170000 -e 0x10000 -r MOUNT_POINT -o CONF-NEW.bin 51 | ``` 52 | 7. Remove modules & deassociate loop-back device 53 | ```sh 54 | $ rmmod mtdblock; rmmod block2mtd 55 | $ losetup -d /dev/loop0 56 | ``` 57 | -------------------------------------------------------------------------------- /genimage/.gitignore: -------------------------------------------------------------------------------- 1 | dumpimage 2 | genimage 3 | -------------------------------------------------------------------------------- /genimage/Makefile: -------------------------------------------------------------------------------- 1 | PARSERDIR = ./iniparser-2.14 2 | 3 | CFLAGS = -Wall -I$(PARSERDIR)/src -m32 -g -Wno-format 4 | #CFLAGS += -DDEBUG # Uncomment to enable debug 5 | LFLAGS = -m32 -L$(PARSERDIR) -g 6 | RM = rm -f 7 | 8 | all: genimage dumpimage 9 | rm fwinfo.o 10 | 11 | $(PARSERDIR)/libini.a: 12 | @(make -C $(PARSERDIR) all) 13 | 14 | genimage: genimage.o fmhcore.o fwinfo.o $(PARSERDIR)/libini.a 15 | @(echo "generating genimage ...") 16 | @($(CC) -o genimage genimage.o fwinfo.o fmhcore.o $(LFLAGS) -lini) 17 | 18 | dumpimage: dumpimage.o fmhcore.o 19 | @(echo "generating dumpimage ...") 20 | @($(CC) -o dumpimage dumpimage.o fmhcore.o $(LFLAGS)) 21 | 22 | 23 | clean: 24 | @($(RM) genimage dumpimage *o) 25 | @(make -C $(PARSERDIR) clean) 26 | 27 | 28 | COMPILE.c=$(CC) $(CFLAGS) -c 29 | .c.o: 30 | @(echo "compiling $< ...") 31 | @($(COMPILE.c) -o $@ $<) 32 | 33 | -------------------------------------------------------------------------------- /genimage/crc32.h: -------------------------------------------------------------------------------- 1 | #ifndef AMI_CRC32_H 2 | #define AMI_CRC32_H 3 | 4 | 5 | UINT32 CrcLookUpTable[256] = 6 | { 7 | 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 8 | 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 9 | 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 10 | 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 11 | 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 12 | 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 13 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 14 | 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 15 | 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 16 | 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 17 | 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 18 | 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 19 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 20 | 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 21 | 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 22 | 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 23 | 24 | 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 25 | 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 26 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 27 | 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 28 | 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 29 | 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 30 | 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 31 | 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 32 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 33 | 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 34 | 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 35 | 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 36 | 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 37 | 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 38 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 39 | 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 40 | 41 | 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 42 | 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 43 | 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 44 | 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 45 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 46 | 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 47 | 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 48 | 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 49 | 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 50 | 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 51 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 52 | 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 53 | 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 54 | 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 55 | 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 56 | 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 57 | 58 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 59 | 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 60 | 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 61 | 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 62 | 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 63 | 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 64 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 65 | 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 66 | 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 67 | 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 68 | 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 69 | 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 70 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 71 | 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 72 | 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 73 | 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /genimage/dumpimage.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "fmh.h" 16 | 17 | static unsigned char FirmwareInfo[64*1024]; 18 | static UINT32 Location; /* Flash Location Value */ 19 | static INT32 BlockSize; /* Size of each Flash Block */ 20 | 21 | static int summary = 0; 22 | 23 | static void update_name(MODULE_INFO *mod, char *name) 24 | { 25 | char *p = name; 26 | 27 | strncpy(name, (char *)mod->Module_Name, 8); 28 | name[8] = '\0'; 29 | 30 | while (*p) { 31 | *p = toupper(*p); 32 | p++; 33 | } 34 | } 35 | 36 | static void dump_fmh(FMH *fmh, MODULE_INFO *mod, char *name, FILE *out) 37 | { 38 | int is_mod = 1; 39 | int comp = 0; 40 | 41 | // printf("*** %s ***\n", name); 42 | 43 | if (summary) { 44 | fprintf(out, "%-16s\t%d.%d\t0x%04x\n", 45 | name, mod->Module_Ver_Major, mod->Module_Ver_Minor, mod->Module_Type); 46 | return; 47 | } 48 | 49 | fprintf(out, "[%s]\n", name); 50 | 51 | if (mod->Module_Type == MODULE_FMH_FIRMWARE 52 | || mod->Module_Type == MODULE_FIRMWARE_1_4) { 53 | is_mod = 0; 54 | } 55 | 56 | /* Version output */ 57 | fprintf(out, "\tMajor\t\t= %d\n\tMinor\t\t= %d\n", 58 | mod->Module_Ver_Major, mod->Module_Ver_Minor); 59 | 60 | /* Type output */ 61 | fprintf(out, "\tType\t\t= 0x%04x\n", mod->Module_Type); 62 | 63 | 64 | if (is_mod) { 65 | /* Alloc output */ 66 | if (fmh->FMH_AllocatedSize - mod->Module_Location > mod->Module_Size + BlockSize) 67 | fprintf(out, "\tAlloc\t\t= %dK\n", 68 | fmh->FMH_AllocatedSize / 1024); 69 | 70 | /* Output flags */ 71 | fprintf(out, "\tCheckSum\t= %s\n", 72 | (mod->Module_Flags & MODULE_FLAG_VALID_CHECKSUM) ? "YES" : "NO"); 73 | 74 | if (mod->Module_Flags & MODULE_FLAG_BOOTPATH_OS) 75 | fprintf(out, "\tBootOS\t\t= YES\n"); 76 | 77 | if (mod->Module_Flags & MODULE_FLAG_BOOTPATH_DIAG) 78 | fprintf(out, "\tBootDIAG\t= YES\n"); 79 | 80 | if (mod->Module_Flags & MODULE_FLAG_BOOTPATH_RECOVERY) 81 | fprintf(out, "\tBootRECO\t= YES\n"); 82 | 83 | if (mod->Module_Flags & MODULE_FLAG_EXECUTE) 84 | fprintf(out, "\tExecute\t\t= YES\n"); 85 | 86 | if (mod->Module_Flags & MODULE_FLAG_COPY_TO_RAM) 87 | fprintf(out, "\tCopyToRAM\t= YES\n"); 88 | 89 | comp = (mod->Module_Flags & MODULE_FLAG_COMPRESSION_MASK) >> MODULE_FLAG_COMPRESSION_LSHIFT; 90 | if (comp > 0) 91 | fprintf(out, "\tCompress\t= %s\n", comp); 92 | 93 | /* Filename output */ 94 | fprintf(out, "\tFile\t\t= %s.bin\n", name); 95 | } 96 | 97 | /* Locate output */ 98 | if (fmh->FMH_Location < BlockSize) 99 | fprintf(out, "\tLocate\t\t= \"START\"\n"); 100 | else if (fmh->FMH_Location == Location) 101 | fprintf(out, "\tLocate\t\t= \"END\"\n"); 102 | else if (fmh->FMH_Location / 1024 < 2049) 103 | fprintf(out, "\tLocate\t\t= %dK\t\t;0x%x\n", 104 | fmh->FMH_Location / 1024, fmh->FMH_Location); 105 | else 106 | fprintf(out, "\tLocate\t\t= 0x%x\t\t;%dK\n", 107 | fmh->FMH_Location, fmh->FMH_Location / 1024); 108 | 109 | if (is_mod) { 110 | /* Offset output */ 111 | if (mod->Module_Location > 0x40) 112 | fprintf(out, "\tOffset\t\t= %dK\n", 113 | mod->Module_Location / 1024); 114 | 115 | /* Load output */ 116 | if (mod->Module_Load_Address != 0xFFFFFFFF) 117 | fprintf(out, "\tLoad\t\t= %dM\n", 118 | mod->Module_Load_Address / 1024 / 1024); 119 | 120 | /* Alternate FMH location output */ 121 | if (fmh->FMH_Location % BlockSize != 0) 122 | fprintf(out, "\tFMHLoc\t\t= 0x%04x\t\t; %dK - 128\n", 123 | fmh->FMH_Location, (fmh->FMH_Location+128) / 1024); 124 | } 125 | 126 | fputs("\n", out); 127 | } 128 | 129 | static void dump_module(FMH *fmh, MODULE_INFO *mod, char *name, FILE *fd, const char *dir) 130 | { 131 | FILE *out; 132 | char outfile[256]; 133 | char *in_p; 134 | 135 | if (mod->Module_Type == MODULE_FMH_FIRMWARE 136 | || mod->Module_Type == MODULE_FIRMWARE_1_4) 137 | { 138 | return; 139 | } 140 | 141 | #if 0 142 | printf("\nFMH Size %08x Location %08x Alloc %08x\n", fmh->FMH_Size, fmh->FMH_Location, fmh->FMH_AllocatedSize); 143 | printf("MOD Size %08x Location %08x\n", mod->Module_Size, mod->Module_Location); 144 | printf("mmap %08x @ %08x\n", fmh->FMH_AllocatedSize, fmh->FMH_Location + mod->Module_Location); 145 | #endif 146 | 147 | printf(" -- processing %s...\n", name); 148 | 149 | in_p = mmap(NULL, fmh->FMH_AllocatedSize, PROT_READ, 150 | MAP_SHARED, fileno(fd), fmh->FMH_Location & (~0xffff)); 151 | 152 | snprintf(outfile, 256, "%s/%s.bin", dir, name); 153 | out = fopen(outfile, "w+"); 154 | if (out == NULL) 155 | { 156 | printf("Error: Unable to create file %s\n", outfile); 157 | return; 158 | } 159 | 160 | if (fwrite(in_p + mod->Module_Location, mod->Module_Size, 1, out) != 1) 161 | { 162 | printf("Error: Unable to write to file %s\n", outfile); 163 | return; 164 | } 165 | 166 | munmap(in_p, fmh->FMH_AllocatedSize); 167 | 168 | fclose(out); 169 | } 170 | 171 | static 172 | void 173 | dump_fwinfo(char *fwinfo, FILE *out) 174 | { 175 | int j; 176 | char *str, *token; 177 | char *key; 178 | char *value; 179 | char *saveptr1, *saveptr2; 180 | char *p; 181 | 182 | /* Check for FirmwareInfo data */ 183 | p = index(fwinfo, 0xff); 184 | if (p == NULL || p == fwinfo) 185 | return; 186 | 187 | *p = '\0'; 188 | // printf("%s\n", fwinfo); 189 | 190 | for (j = 1, str = fwinfo; ; j++, str = NULL) 191 | { 192 | token = strtok_r(str, "\n", &saveptr1); 193 | if (token == NULL) 194 | break; 195 | 196 | key = strtok_r(token, "=", &saveptr2); 197 | if (key == NULL) 198 | continue; 199 | value = strtok_r(NULL, "=", &saveptr2); 200 | if (value == NULL) 201 | continue; 202 | printf("%s=\"%s\"\n", key, value); 203 | if (summary) 204 | continue; 205 | 206 | if (!strcmp(key, "FW_VERSION")) { 207 | int mj, mn, no; 208 | if (sscanf(value, "%d.%d.%d", &mj, &mn, &no) == 3) 209 | { 210 | fprintf(out, "\tBuildNo\t\t= %d\n", no); 211 | } 212 | } else if (!strcmp(key, "FW_PRODUCTID")) { 213 | fprintf(out, "\tProductId\t= %d\n", atoi(value)); 214 | } else if (!strcmp(key, "FW_PRODUCTNAME")) { 215 | fprintf(out, "\tProductName\t= \"%s\"\n", value); 216 | } else if (!strncmp(key, "OEM_", 4)) { 217 | printf(" *** TODO: Process OEM keys here! ***\n"); 218 | } 219 | } 220 | } 221 | 222 | static 223 | void 224 | Usage(char *Prog, int status) 225 | { 226 | printf("Usage is %s \n", Prog); 227 | printf("Args are :\n"); 228 | printf("\t -i Input Firmware File\n"); 229 | printf("\t -o Output Firmware Path\n"); 230 | printf("\t -b Block Size (in kB, default 64)\n"); 231 | printf("\t -s Summary\n"); 232 | printf("\t -f Offset to the FMH header\n"); 233 | printf("\n"); 234 | exit(status); 235 | } 236 | 237 | int 238 | main(int argc, char *argv[]) 239 | { 240 | int opt; 241 | long fmh_offset = 0; 242 | 243 | /* Global Information */ 244 | char *OutDir; /* Location of Output Files */ 245 | char *fw_file; 246 | 247 | /* Output File Creation Related */ 248 | FILE *Outfd; /* Output File Descriptor */ 249 | char ini_name[256]; 250 | 251 | /* FMH Related */ 252 | FILE *Infd; 253 | FMH *fmh = NULL; 254 | MODULE_INFO *mod = NULL; /* Module Information */ 255 | char ModuleName[9]; 256 | 257 | /* RACTRENDS releted */ 258 | // int FirmwareMajor,FirmwareMinor; 259 | struct stat stat; 260 | 261 | /* Initialize with empty values */ 262 | OutDir = NULL; 263 | fw_file = NULL; 264 | ini_name[0] = '\0'; 265 | BlockSize = 0; 266 | 267 | while ((opt = getopt(argc, argv, "i:o:b:f:hs")) != -1) 268 | { 269 | switch (opt) 270 | { 271 | case 'i': 272 | fw_file = strdup(optarg); 273 | break; 274 | case 'o': 275 | OutDir = strdup(optarg); 276 | break; 277 | case 'b': 278 | BlockSize = atoi(optarg)*0x1000; 279 | break; 280 | case 'f': 281 | fmh_offset = strtol(optarg, NULL, 16); 282 | break; 283 | case 's': 284 | summary = 1; 285 | break; 286 | default: 287 | Usage("dumpimage", opt != 'h'); 288 | break; 289 | } 290 | } 291 | 292 | if (fw_file == NULL || (OutDir == NULL && !summary)) 293 | Usage("dumpimage", 2); 294 | 295 | if (!summary) 296 | { 297 | snprintf(ini_name, 256, "%s/genimage.ini", OutDir); 298 | 299 | if (mkdir(OutDir, 0755) < 0) 300 | { 301 | perror("Error: Unable to create directory"); 302 | return 3; 303 | } 304 | } 305 | 306 | if (BlockSize == 0) 307 | BlockSize = 0x10 * 0x1000; 308 | 309 | Infd = fopen(fw_file, "r"); 310 | if (Infd == NULL) 311 | { 312 | printf("Error: Unable to open firmware file %s\n", fw_file); 313 | return 3; 314 | } 315 | 316 | if (fstat(fileno(Infd), &stat) < 0) 317 | { 318 | printf("Error: Stat failed for firmware file %s\n", fw_file); 319 | return 3; 320 | } 321 | 322 | if (fmh_offset == 0) 323 | { 324 | if (fseek(Infd, -BlockSize, SEEK_END) < 0) 325 | { 326 | printf("Error: Seek to the end of firmware file %s failed\n", fw_file); 327 | return 3; 328 | } 329 | } else { 330 | if (fseek(Infd, fmh_offset, SEEK_SET) < 0) 331 | { 332 | printf("Error: Seek to the specified FMH offset in %s failed\n", fw_file); 333 | return 3; 334 | } 335 | } 336 | 337 | if (fread(FirmwareInfo, BlockSize, 1, Infd) != 1) { 338 | printf("Error: Read of firmware file %s failed\n", fw_file); 339 | return 3; 340 | } 341 | 342 | fmh = ScanforFMH(FirmwareInfo, BlockSize); 343 | if (fmh == NULL) 344 | { 345 | printf("Error: Can not find FMH header in %s\n", fw_file); 346 | return 3; 347 | } 348 | 349 | if (!summary) 350 | { 351 | Outfd = fopen(ini_name, "w+"); 352 | if (Outfd == NULL) 353 | { 354 | printf("Error: Unable to open output file %s\n", ini_name); 355 | return 3; 356 | } 357 | } 358 | else 359 | { 360 | Outfd = stdout; 361 | } 362 | 363 | mod = &(fmh->Module_Info); 364 | update_name(mod, ModuleName); 365 | 366 | Location = fmh->FMH_Location; 367 | 368 | if (!summary) 369 | { 370 | fprintf(Outfd, "[GLOBAL]\n\tOutput \t= %s\n\tFlashSize \t= %dM\n\tBlockSize\t= %dK\n", 371 | basename(fw_file), stat.st_size / 0x100000, BlockSize / 1024); 372 | } 373 | 374 | dump_fwinfo((char *)FirmwareInfo+0x40, Outfd); 375 | 376 | if (!summary) 377 | fputs("\n", Outfd); 378 | else 379 | fprintf(Outfd, "--------------------------------------\n"); 380 | dump_fmh(fmh, mod, ModuleName, Outfd); 381 | 382 | #if 0 383 | FirmwareMajor = mod->Module_Ver_Major; 384 | FirmwareMinor = mod->Module_Ver_Minor; 385 | 386 | printf("FW %d.%d\n", FirmwareMajor, FirmwareMinor); 387 | printf("Size %08x Location %08x\n", fmh->FMH_Size, fmh->FMH_Location); 388 | #endif 389 | fseek(Infd, 0, SEEK_SET); 390 | 391 | while (fread(FirmwareInfo, BlockSize, 1, Infd) == 1) 392 | { 393 | fmh = ScanforFMH(FirmwareInfo, BlockSize); 394 | if (fmh == NULL) 395 | { 396 | // Possible GAP, try next block 397 | continue; 398 | } 399 | 400 | // Last block reached, stop 401 | if (fmh->FMH_Location == Location) 402 | break; 403 | 404 | mod = &(fmh->Module_Info); 405 | update_name(mod, ModuleName); 406 | 407 | dump_fmh(fmh, mod, ModuleName, Outfd); 408 | if (!summary) 409 | dump_module(fmh, mod, ModuleName, Infd, OutDir); 410 | 411 | fseek(Infd, fmh->FMH_AllocatedSize - BlockSize, SEEK_CUR); 412 | } 413 | 414 | fclose(Infd); 415 | 416 | if (!summary) 417 | fclose(Outfd); 418 | 419 | return 0; 420 | } 421 | -------------------------------------------------------------------------------- /genimage/fmh.h: -------------------------------------------------------------------------------- 1 | #ifndef __AMI_FMH_H__ 2 | #define __AMI_FMH_H__ 3 | 4 | typedef unsigned long UINT32; 5 | typedef long INT32; 6 | 7 | #define FMH_SIGNATURE "$MODULE$" 8 | #define FMH_END_SIGNATURE 0x55AA 9 | #define FMH_SIZE 64 10 | #define FMH_MAJOR 1 11 | #define FMH_MINOR 5 12 | 13 | /* 14 | typedef struct 15 | { 16 | unsigned short BootPathID:3; 17 | unsigned short CopyToRAM:1; 18 | unsigned short Execute:1; 19 | unsigned short Compress:3; 20 | unsigned short ValidChecksum:1; 21 | unsigned short Reserved:7; 22 | } __attribute__ ((packed)) MODULE_FLAGS; 23 | */ 24 | 25 | /* Module Information Structure */ 26 | typedef struct 27 | { 28 | unsigned char Module_Name[8]; 29 | unsigned char Module_Ver_Major; 30 | unsigned char Module_Ver_Minor; 31 | unsigned short Module_Type; /* Refer Module Type Values Below */ 32 | UINT32 Module_Location; /* Offset to Module from start */ 33 | UINT32 Module_Size; 34 | unsigned short Module_Flags; /* Refer Module Flags Values Below */ 35 | UINT32 Module_Load_Address; 36 | UINT32 Module_Checksum; /* CRC 32 */ 37 | unsigned char Module_Reserved[8]; 38 | } __attribute__ ((packed)) MODULE_INFO; 39 | 40 | /* Flash Module Header */ 41 | typedef struct 42 | { 43 | unsigned char FMH_Signature[8]; /* "$MODULE$" */ 44 | unsigned char FMH_Ver_Major; /* 1 */ 45 | unsigned char FMH_Ver_Minor; /* 5 */ 46 | unsigned short FMH_Size; /* For FHM Ver 1.5 this is 64 */ 47 | UINT32 FMH_AllocatedSize; 48 | UINT32 FMH_Location; 49 | unsigned char FMH_Reserved[3]; 50 | unsigned char FMH_Header_Checksum; /* Modulo 100 */ 51 | MODULE_INFO Module_Info; 52 | unsigned short FMH_End_Signature; /* 0x55AA */ 53 | } __attribute__ ((packed)) FMH; 54 | 55 | /* Alternate FMH Location - At the end of first erase block */ 56 | typedef struct 57 | { 58 | unsigned short FMH_End_Signature; /* 0x55AA */ 59 | unsigned char FMH_Header_Checksum; /* Modulo 100 */ 60 | unsigned char FMH_Reserved; 61 | UINT32 FMH_Link_Address; /* Actual FMH offset from erase blk start*/ 62 | unsigned char FMH_Signature[8]; /* "$MODULE$" */ 63 | } __attribute__ ((packed)) ALT_FMH; 64 | 65 | 66 | /*Values for FMH_Link_Address*/ 67 | #define INVALID_FMH_OFFSET 0xFFFFFFFF 68 | 69 | 70 | /* Values for LSB of Module Type */ 71 | #define MODULE_UNKNOWN 0x00 /* Unknown Module Type */ /* All */ 72 | #define MODULE_BOOTLOADER 0x01 /* Boot Loader */ /* All */ 73 | #define MODULE_FMH_FIRMWARE 0x02 /* Info about firmware */ /* All */ 74 | #define MODULE_KERNEL 0x03 /* OS Kernel */ /* All */ 75 | #define MODULE_FPGA 0x04 /* FPGA Microcode */ /* All */ 76 | #define MODULE_ELF 0x05 /* ELF Executable Image */ /* All */ 77 | #define MODULE_PIMAGE 0x06 /* U-Boot Linux Image */ /* < 1.4 */ 78 | #define MODULE_INITRD_CRAMFS 0x07 /* Initrd image of cramfs*/ /* < 1.4 */ 79 | #define MODULE_LINUX_KERNEL 0x08 /* Linux Kernel Image */ /* >= 1.4 */ 80 | #define MODULE_LINUX_ROOTFS 0x09 /* Linux Root FileSystem */ /* >= 1.4 */ 81 | #define MODULE_JFFS 0x10 /* JFFS File System */ /* < 1.3 */ 82 | #define MODULE_JFFS2 0x11 /* JFFS2 File System */ /* < 1.3 */ 83 | #define MODULE_JFFS_CONFIG 0x20 /* 1.3 Only */ 84 | #define MODULE_JFFS2_CONFIG 0x21 /* 1.3 Only */ 85 | #define MODULE_CONFIG 0x30 /* Configuration */ /* >= 1.4 */ 86 | #define MODULE_WEB 0x40 /* Web pages */ /* >= 1.4 */ 87 | #define MODULE_PDK 0x50 /* PDK */ /* >= 1.4 */ 88 | 89 | /* Values for MSBof Module Type = Module Format */ 90 | #define MODULE_FORMAT_BACKWARD 0x00 /* Set for Backward comaptible till 1.3 */ 91 | #define MODULE_FORMAT_BINARY 0x01 92 | #define MODULE_FORMAT_FIRMWARE_INFO 0x02 93 | #define MODULE_FORMAT_UBOOT_WRAP 0x03 94 | #define MODULE_FORMAT_ELF 0x04 95 | #define MODULE_FORMAT_CRAMFS 0x10 96 | #define MODULE_FORMAT_JFFS 0x11 97 | #define MODULE_FORMAT_JFFS2 0x12 98 | #define MODULE_FORMAT_INITRD 0x80 99 | 100 | #define MODULE_FIRMWARE_1_4 ((MODULE_FORMAT_FIRMWARE_INFO << 8) | (MODULE_FMH_FIRMWARE)) 101 | 102 | /* FMH header field offsets */ 103 | #define FMH_MODULE_CHECKSUM_START_OFFSET 0x32 /* Module CheckSum Location Begin */ 104 | #define FMH_MODULE_CHCKSUM_END_OFFSET 0x35 /* Module CheckSum Location End */ 105 | #define FMH_FMH_HEADER_CHECKSUM_OFFSET 0x17 /* FMH Header CheckSum Location */ 106 | 107 | /* Values for Module Flags */ 108 | #define MODULE_FLAG_BOOTPATH_OS 0x0001 109 | #define MODULE_FLAG_BOOTPATH_DIAG 0x0002 110 | #define MODULE_FLAG_BOOTPATH_RECOVERY 0x0004 111 | #define MODULE_FLAG_COPY_TO_RAM 0x0008 112 | #define MODULE_FLAG_EXECUTE 0x0010 113 | #define MODULE_FLAG_COMPRESSION_MASK 0x00E0 /* Refer Compression Type values */ 114 | #define MODULE_FLAG_COMPRESSION_LSHIFT 5 115 | #define MODULE_FLAG_VALID_CHECKSUM 0x0100 /* Validate Checksum if this is set */ 116 | 117 | /* Values for Compression */ 118 | #define MODULE_COMPRESSION_NONE 0x00 119 | #define MODULE_COMPRESSION_MINILZO_1X 0x01 120 | #define MODULE_COMPRESSION_GZIP 0x02 121 | 122 | #include 123 | #define host_to_le16(x) __cpu_to_le16((x)) 124 | #define host_to_le32(x) __cpu_to_le32((x)) 125 | #define le16_to_host(x) __le16_to_cpu((x)) 126 | #define le32_to_host(x) __le32_to_cpu((x)) 127 | 128 | /* Function Prototypes */ 129 | FMH* ScanforFMH(unsigned char *SectorAddr, UINT32 SectorSize); 130 | void CreateFMH(FMH *fmh,UINT32 AllocatedSize, MODULE_INFO *mod,UINT32 Location); 131 | void CreateAlternateFMH(ALT_FMH *altfmh,UINT32 FMH_Offset); 132 | 133 | /* CRC32 Related */ 134 | UINT32 CalculateCRC32(unsigned char *Buffer, UINT32 Size); 135 | void BeginCRC32(UINT32 *crc32); 136 | void DoCRC32(UINT32 *crc32, unsigned char Data); 137 | void EndCRC32(UINT32 *crc32); 138 | #endif 139 | -------------------------------------------------------------------------------- /genimage/fmh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | import numpy as np 5 | import datetime 6 | import binascii 7 | from struct import pack, unpack 8 | 9 | try: 10 | import ConfigParser as cp 11 | except: 12 | import configparser as cp 13 | 14 | FMH_SIGNATURE = np.fromstring(b'$MODULE$', dtype=np.uint32) 15 | FMH_MAJOR = 1 16 | FMH_MINOR = 5 17 | FMH_END_SIGNATURE = 0x55aa 18 | FMH_SIZE = 64 >> 2 19 | ALT_FMH_SIZE = 16 >> 2 20 | 21 | MODULE_FMH_FIRMWARE = 0x02 22 | 23 | MODULE_FORMAT_FIRMWARE_INFO = 0x02 24 | 25 | MODULE_FIRMWARE_1_4 = ((MODULE_FORMAT_FIRMWARE_INFO << 8) | MODULE_FMH_FIRMWARE) 26 | 27 | MODULE_FLAG_BOOTPATH_OS = 0x0001 28 | MODULE_FLAG_BOOTPATH_DIAG = 0x0002 29 | MODULE_FLAG_BOOTPATH_RECOVERY = 0x0004 30 | MODULE_FLAG_COPY_TO_RAM = 0x0008 31 | MODULE_FLAG_EXECUTE = 0x0010 32 | MODULE_FLAG_COMPRESSION_MASK = 0x00e0 33 | MODULE_FLAG_COMPRESSION_LSHIFT = 5 34 | MODULE_FLAG_VALID_CHECKSUM = 0x0100 35 | 36 | INVALID_FMH_OFFSET = 0xffffffff 37 | 38 | FMH_MODULE_CHECKSUM_OFFSET = 0x32 39 | 40 | OFF_FMH_ALLOC = 3 41 | OFF_FMH_LOC = 4 42 | OFF_FMH_MODULE = 6 43 | OFF_FMH_END_SIG = 15 44 | OFF_MOD_TYPE = 2 45 | OFF_MOD_LOC = 3 46 | OFF_MOD_SIZE = 4 47 | OFF_MOD_FLAGS = 5 48 | OFF_MOD_LOAD = 5 49 | OFF_MOD_CRC32 = 6 50 | 51 | def scan_for_fmh(image, offset, block_size): 52 | def validate100(offset, size): 53 | return np.sum(image[offset:offset+size].view(dtype=np.uint8), dtype=np.uint8) == 0 54 | 55 | def normal(offset): 56 | if not (image[offset:offset+2] == FMH_SIGNATURE).all(): 57 | return INVALID_FMH_OFFSET 58 | if (image[offset+OFF_FMH_END_SIG] >> 16) != FMH_END_SIGNATURE: 59 | return INVALID_FMH_OFFSET 60 | if not validate100(offset, FMH_SIZE): 61 | return INVALID_FMH_OFFSET 62 | return offset 63 | 64 | def alternate(offset): 65 | if not (image[offset+2:offset+4] == FMH_SIGNATURE).all(): 66 | return INVALID_FMH_OFFSET 67 | if (image[offset] & 0xffff) != FMH_END_SIGNATURE: 68 | return INVALID_FMH_OFFSET 69 | if not validate100(offset, ALT_FMH_SIZE): 70 | return INVALID_FMH_OFFSET 71 | return image[offset+1] >> 2 72 | 73 | fmh = normal(offset) 74 | if fmh != INVALID_FMH_OFFSET: 75 | return fmh 76 | fmh = alternate(offset + block_size - ALT_FMH_SIZE) 77 | if fmh != INVALID_FMH_OFFSET: 78 | fmh = normal(offset + fmh) 79 | return fmh 80 | 81 | def build_image(cfg): 82 | def parse_bytes(num): 83 | fix = num[-1] 84 | try: 85 | num = int(num, 0) 86 | except: 87 | num = int(num[:-1], 0) 88 | if fix == 'M': 89 | num *= 1024 90 | fix = 'K' 91 | if fix == 'K': 92 | num *= 1024 93 | return num 94 | 95 | def create_fwinfo(mj, mn): 96 | buildno = cfg.getint('GLOBAL', 'BuildNo') 97 | desc = os.getenv('FW_DESC') 98 | _now = datetime.datetime.now() 99 | _date = os.getenv('FW_DATE') 100 | if not _date: 101 | _date = _now.strftime('%b %d %Y') 102 | _time = os.getenv('FW_BUILDTIME') 103 | if not _time: 104 | _time = _now.strftime('%H:%M:%S') 105 | out = 'FW_VERSION={}.{}.{}\nFW_DATE={}\nFW_BUILDTIME={}\n'.format( 106 | mj, mn, buildno, _date, _time) 107 | if desc: 108 | out += 'FW_DESC={}\n'.format(desc) 109 | else: 110 | out += 'FW_DESC=WARNING : UNOFFICIAL BUILD!! \n' 111 | try: out += 'FW_PRODUCTID={}\n'.format(cfg.getint('GLOBAL', 'ProductId')) 112 | except: pass 113 | try: out += 'FW_PRODCUTNAME={}\n'.format(cfg.get('GLOBAL', 'ProductName')) 114 | except: pass 115 | return out 116 | # if len(out) % 4 == 0: 117 | # return out 118 | # return out + '\xff' * (4 - (len(out) % 4)) 119 | 120 | outname = os.path.dirname(sys.argv[0])+'/'+cfg.get('GLOBAL', 'Output')+'.new' 121 | flash_size = parse_bytes(cfg.get('GLOBAL', 'FlashSize')) >> 2 122 | block_size = parse_bytes(cfg.get('GLOBAL', 'BlockSize')) >> 2 123 | output = np.memmap(outname, mode='w+', dtype=np.uint32, shape=(flash_size,)) 124 | output[:] = 0xffffffff 125 | image_header_start = 0xffffffff 126 | 127 | mods = [] 128 | for modname in cfg.sections(): 129 | if modname == 'GLOBAL': 130 | continue 131 | # Module version 132 | mj = cfg.getint(modname, 'Major') 133 | mn = cfg.getint(modname, 'Minor') 134 | 135 | # Module type 136 | tp = int(cfg.get(modname, 'Type'), 0) 137 | mformat = tp >> 8 138 | 139 | # Location 140 | try: fmhloc = parse_bytes(cfg.get(modname, 'FMHLoc')) 141 | except: fmhloc = 0 142 | if fmhloc != 0: 143 | modloc = 0 144 | elif tp in (0x10,0x11,0x20,0x21) or mformat in (0x11, 0x12): 145 | modloc = block_size << 2 146 | else: 147 | modloc = 0x40 148 | try: modloc = parse_bytes(cfg.get(modname, 'Offset')) 149 | except: pass 150 | 151 | # Flags 152 | flags = 0 153 | try: 154 | if cfg.getboolean(modname, 'BootOS'): flags |= MODULE_FLAG_BOOTPATH_OS 155 | except: pass 156 | try: 157 | if cfg.getboolean(modname, 'BootDIAG'): flags |= MODULE_FLAG_BOOTPATH_DIAG 158 | except: pass 159 | try: 160 | if cfg.getboolean(modname, 'BootRECO'): flags |= MODULE_FLAG_BOOTPATH_RECOVERY 161 | except: pass 162 | try: 163 | if cfg.getboolean(modname, 'CopyToRAM'): flags |= MODULE_FLAG_COPY_TO_RAM 164 | except: pass 165 | try: 166 | if cfg.getboolean(modname, 'Execute'): flags |= MODULE_FLAG_EXECUTE 167 | except: pass 168 | try: 169 | if cfg.getboolean(modname, 'CheckSum'): flags |= MODULE_FLAG_VALID_CHECKSUM 170 | except: pass 171 | try: flags |= int(cfg.get(modname, 'Compress'), 0) << MODULE_FLAG_COMPRESSION_LSHIFT 172 | except: pass 173 | 174 | # Load address 175 | try: load = parse_bytes(cfg.get(modname, 'Load')) 176 | except: load = 0xffffffff 177 | if load == 0xffffffff: 178 | flags &= ~MODULE_FLAG_COPY_TO_RAM 179 | 180 | # Allocation size 181 | try: alloc = parse_bytes(cfg.get(modname, 'Alloc')) 182 | except: alloc = 0 183 | 184 | if tp == MODULE_FMH_FIRMWARE or tp == MODULE_FIRMWARE_1_4: 185 | alloc = block_size << 2 186 | 187 | # Location 188 | loc = 0xffffffff 189 | _loc = cfg.get(modname, 'Locate') 190 | if _loc == 'START': 191 | loc = 0 192 | elif _loc == 'END': 193 | loc = flash_size - (alloc >> 2) 194 | if loc == 0xffffffff: 195 | loc = parse_bytes(_loc) >> 2 196 | if loc + (alloc >> 2) > flash_size: 197 | print('ERROR: module location {}, alloc {} > flash {} for {}'.format( 198 | loc << 2, alloc, flash_size << 2, modname)) 199 | break 200 | 201 | # TODO: Update chain for overlap checks 202 | 203 | if tp == MODULE_FMH_FIRMWARE or tp == MODULE_FIRMWARE_1_4: 204 | _mj = os.getenv('FW_MAJOR') 205 | _mn = os.getenv('FW_MINOR') 206 | if _mj: mj = int(_mj, 0) 207 | if _mn: mn = int(_mn, 0) 208 | _fwinfo = create_fwinfo(mj, mn) 209 | modsize = len(_fwinfo) 210 | if modsize > ((64 * 1024) - 0x40): 211 | modsize = 0 212 | fmh_cksum = 0 213 | image_header_start = loc 214 | if modsize > 0: 215 | output.view(dtype=np.uint8)[(loc << 2)+modloc:(loc << 2) + modloc + modsize] = np.fromstring(_fwinfo, dtype=np.uint8) 216 | else: 217 | # Mandatory field `File' 218 | infile = np.memmap(cfg.get(modname, 'File'), mode='r', dtype=np.uint32) 219 | modsize = len(infile) << 2 220 | minsize = modloc + modsize 221 | minsize += (block_size << 2) - 1 222 | minsize = minsize/(block_size << 2) * (block_size << 2) 223 | if alloc < minsize: 224 | alloc = minsize 225 | fmh_cksum = binascii.crc32(infile, 0) & 0xffffffff 226 | print('%s %x %d %x %x' % (modname, fmh_cksum, len(infile), alloc, modloc)) 227 | # Write module 228 | output[loc + (modloc >> 2):loc+(modloc >> 2)+len(infile)] = infile 229 | 230 | # CreateFMH 231 | mname = modname[:8].lower() 232 | if len(mname) != 8: 233 | mname += '\x00' * (8 - len(mname) % 8) 234 | fmh = np.array([ 235 | FMH_SIGNATURE[0], 236 | FMH_SIGNATURE[1], 237 | FMH_SIZE << 18 | FMH_MINOR << 8 | FMH_MAJOR, 238 | alloc, 239 | (loc << 2) + fmhloc, 240 | 0x00000000, 241 | # Module info 242 | np.fromstring(mname[:4], dtype=np.uint32), 243 | np.fromstring(mname[4:8], dtype=np.uint32), 244 | tp << 16 | mn << 8 | mj, 245 | modloc, 246 | modsize, 247 | (load & 0xffff) << 16 | flags & 0xffff, 248 | fmh_cksum << 16 | load >> 16, 249 | fmh_cksum >> 16, 250 | 0x00000000, 251 | FMH_END_SIGNATURE << 16, 252 | ], dtype=np.uint32) 253 | fmh[5] = ((~np.sum(fmh.view(dtype=np.uint8), dtype=np.uint8))+1) << 24 254 | 255 | if fmhloc != 0: 256 | altfmh = np.array([ 257 | FMH_END_SIGNATURE, 258 | fmhloc, 259 | FMH_SIGNATURE[0], 260 | FMH_SIGNATURE[1], 261 | ], dtype=np.uint32) 262 | altfmh[0] |= ((~np.sum(altfmh.view(dtype=np.uint8), dtype=np.uint8))+1) << 16 263 | output[loc+(fmhloc >> 2):loc+(fmhloc >> 2) + len(fmh)] = fmh 264 | output[loc+(block_size - 4):loc+block_size] = altfmh 265 | else: 266 | output[loc:loc+len(fmh)] = fmh 267 | 268 | if image_header_start != 0xffffff: 269 | output8 = output.view(dtype=np.uint8) 270 | off8 = image_header_start << 2 271 | cksum = binascii.crc32(output8[:off8 + 0x17], 0) & 0xffffffff 272 | cksum = binascii.crc32(output8[off8 + 0x18:off8 + 0x32], cksum) & 0xffffffff 273 | cksum = binascii.crc32(output8[off8 + 0x36:off8 + (block_size << 2)], cksum) & 0xffffffff 274 | output8[off8+FMH_MODULE_CHECKSUM_OFFSET:off8+FMH_MODULE_CHECKSUM_OFFSET+4].view(dtype=np.uint32)[:] = cksum 275 | output8[off8+0x17] = 0x00 276 | output8[off8+0x17] = (~np.sum(output8[off8:off8+(FMH_SIZE << 2)], dtype=np.uint8))+1 277 | 278 | output.flush() 279 | # del output 280 | 281 | def dump_image(cfg, fwimgname): 282 | def name(mod): 283 | return image[mod:mod+2].tostring().replace('\x00','').upper() 284 | 285 | def dump_fwinfo(offset): 286 | # Get string end position 287 | idx = np.where(image[offset:offset+block_size].view(dtype=np.uint8) == 0xff) 288 | if not len(idx[0]): 289 | return 290 | desc = image.view(dtype=np.uint8)[offset << 2:(offset << 2)+idx[0][0]].tostring() 291 | for s in desc.split('\n'): 292 | try: 293 | k,v = s.split('=') 294 | except ValueError: 295 | continue 296 | print('{}=\"{}\"'.format(k, v)) 297 | if summary: 298 | continue 299 | if k == 'FW_VERSION': 300 | try: 301 | mj, mn, no, _ = v.split('.') 302 | except ValueError: 303 | try: 304 | mj, mn, no = v.split('.') 305 | except ValueError: 306 | continue 307 | cfg.set(modname, 'BuildNo', no) 308 | elif k == 'FW_PRODUCTID': 309 | cfg.set(modname, 'ProductId', v) 310 | elif k[:4] == 'OEM_': 311 | print(' *** TODO: Process OEM keys here! ***') 312 | 313 | def dump_fmh(fmh, mod, modname): 314 | mj = image[mod + OFF_MOD_TYPE] & 0xff 315 | mn = (image[mod + OFF_MOD_TYPE] >> 8) & 0xff 316 | tp = image[mod + OFF_MOD_TYPE] >> 16 317 | if summary: 318 | print('{}\t{}.{}\t0x{:x}\n'.format(modname, mj, mn, tp)) 319 | return 320 | 321 | is_mod = not (tp == MODULE_FMH_FIRMWARE or tp == MODULE_FIRMWARE_1_4) 322 | cfg.add_section(modname) 323 | cfg.set(modname, 'Major', mj) 324 | cfg.set(modname, 'Minor', mn) 325 | cfg.set(modname, 'Type', '0x{:04x}'.format(tp)) 326 | 327 | if is_mod: 328 | # Allocate output 329 | if image[fmh + OFF_FMH_ALLOC] - image[mod + OFF_MOD_LOC] > image[mod + OFF_MOD_SIZE] + (block_size << 2): 330 | cfg.set(modname, 'Alloc', '{}K'.format(image[fmh + OFF_FMH_ALLOC] >> 10)) 331 | 332 | # Output flags 333 | flags = image[mod + OFF_MOD_FLAGS] & 0xffff 334 | cfg.set(modname, 'CheckSum', 'YES' if (flags & MODULE_FLAG_VALID_CHECKSUM) else 'NO') 335 | if flags & MODULE_FLAG_BOOTPATH_OS: 336 | cfg.set(modname, 'BootOS', 'YES') 337 | if flags & MODULE_FLAG_BOOTPATH_DIAG: 338 | cfg.set(modname, 'BootDIAG', 'YES') 339 | if flags & MODULE_FLAG_BOOTPATH_RECOVERY: 340 | cfg.set(modname, 'BootRECO', 'YES') 341 | if flags & MODULE_FLAG_EXECUTE: 342 | cfg.set(modname, 'Execute', 'YES') 343 | if flags & MODULE_FLAG_COPY_TO_RAM: 344 | cfg.set(modname, 'CopyToRAM', 'YES') 345 | comp = (flags & MODULE_FLAG_COMPRESSION_MASK) >> MODULE_FLAG_COMPRESSION_LSHIFT 346 | if comp > 0: 347 | cfg.set(modname, 'Compress', comp) 348 | 349 | # Filename 350 | cfg.set(modname, 'File', '{}.bin'.format(modname)) 351 | 352 | # Location 353 | if image[fmh + OFF_FMH_LOC] < (block_size << 2): 354 | cfg.set(modname, 'Locate', 'START') 355 | elif image[fmh + OFF_FMH_LOC] == loc: 356 | cfg.set(modname, 'Locate', 'END') 357 | elif image[fmh + OFF_FMH_LOC] >> 10 < 0x801: 358 | cfg.set(modname, 'Locate', '{}K'.format(image[fmh + OFF_FMH_LOC] >> 10)) 359 | else: 360 | cfg.set(modname, 'Locate', '0x{:x}'.format(image[fmh + OFF_FMH_LOC])) 361 | 362 | if is_mod: 363 | # Offset output 364 | if image[mod + OFF_MOD_LOC] > 0x40: 365 | cfg.set(modname, 'Offset', '{}K'.format(image[mod + OFF_MOD_LOC] >> 10)) 366 | 367 | # Load output 368 | load = (image[mod + OFF_MOD_LOAD] >> 16) | ((image[mod + OFF_MOD_LOAD + 1] & 0xffff) << 16) 369 | if load != 0xffffffff: 370 | cfg.set(modname, 'Load', '{}M'.format(load >> 20)) 371 | 372 | # Alternate FMH location 373 | if image[fmh + OFF_FMH_LOC] % block_size != 0: 374 | cfg.set(modname, 'FMHLoc', '0x{:04x}'.format(image[fmh + OFF_FMH_LOC])) 375 | 376 | def dump_module(fmh, mod, modname, dirname): 377 | tp = image[mod + OFF_MOD_TYPE] >> 16 378 | if tp == MODULE_FMH_FIRMWARE or tp == MODULE_FIRMWARE_1_4: 379 | return 380 | 381 | print(' -- processing {}...'.format(modname)) 382 | _off = ((image[fmh + OFF_FMH_LOC] & (~0xffff)) >> 2) + (image[mod + OFF_MOD_LOC] >> 2) 383 | _len = image[mod + OFF_MOD_SIZE] >> 2 384 | image[_off:_off+_len].tofile('{}/{}.bin'.format(dirname, modname)) 385 | 386 | summary = False 387 | block_size = 0 388 | image = np.memmap(fwimgname, dtype=np.uint32) 389 | if not block_size: 390 | block_size = 0x10 * 0x1000 391 | 392 | block_size >>= 2 # align by 4 bytes 393 | fwinfo = len(image) - block_size 394 | fmh = scan_for_fmh(image, fwinfo, block_size) 395 | if fmh == INVALID_FMH_OFFSET: 396 | raise Exception('Cannot find FMH header') 397 | mod = fmh + OFF_FMH_MODULE 398 | loc = image[fmh + OFF_FMH_LOC] 399 | 400 | modname = 'GLOBAL' 401 | if not summary: 402 | cfg.add_section(modname) 403 | cfg.set(modname, 'Output', os.path.basename(fwimgname)) 404 | cfg.set(modname, 'FlashSize', '{}M'.format(len(image) >> 18)) 405 | cfg.set(modname, 'BlockSize', '{}K'.format(block_size >> 8)) 406 | 407 | dump_fwinfo(fwinfo+0x10) 408 | 409 | modname = name(mod) 410 | 411 | if summary: 412 | out.write('-----------------------------------\n') 413 | 414 | dump_fmh(fmh, mod, modname) 415 | 416 | fwinfo = 0 417 | while fwinfo < len(image) - block_size: 418 | fmh = scan_for_fmh(image, fwinfo, block_size) 419 | if fmh == INVALID_FMH_OFFSET: 420 | # Possible GAP 421 | fwinfo += block_size 422 | continue 423 | 424 | # Last block reached, stop 425 | if image[fmh + 4] == loc: 426 | break 427 | 428 | mod = fmh + OFF_FMH_MODULE 429 | modname = name(mod) 430 | 431 | dump_fmh(fmh, mod, modname) 432 | if not summary: 433 | dump_module(fmh, mod, modname, sys.argv[2]+'.dump') 434 | 435 | fwinfo += (image[fmh + OFF_FMH_ALLOC] >> 2) - block_size 436 | 437 | image.flush() 438 | # del image 439 | 440 | if __name__ == '__main__': 441 | if len(sys.argv) == 2 and sys.argv[1] == '-b': 442 | cfg = cp.ConfigParser() 443 | cfg.optionxform = str 444 | cfg.read('genimage.ini') 445 | build_image(cfg) 446 | elif len(sys.argv) == 3 and sys.argv[1] == '-d': 447 | try: os.mkdir(sys.argv[2]+'.dump') 448 | except: pass 449 | cfg = cp.ConfigParser() 450 | cfg.optionxform = str 451 | with open(sys.argv[2]+'.dump/genimage.ini', 'w+') as f: 452 | dump_image(cfg, sys.argv[2]) 453 | cfg.write(f) 454 | else: 455 | print('Usage: fmh.py [-d firmware.ima | -b]') 456 | sys.exit(1) 457 | -------------------------------------------------------------------------------- /genimage/fmhcore.c: -------------------------------------------------------------------------------- 1 | #ifdef __KERNEL__ 2 | #ifdef __UBOOT__ 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | #else 9 | #include 10 | #include 11 | #endif 12 | #include "fmh.h" 13 | #include "crc32.h" 14 | 15 | 16 | unsigned char CalculateModule100(unsigned char *Buffer, UINT32 Size); 17 | static FMH * CheckForNormalFMH(FMH *fmh); 18 | static UINT32 CheckForAlternateFMH(ALT_FMH *altfmh); 19 | 20 | 21 | unsigned char 22 | CalculateModule100(unsigned char *Buffer, UINT32 Size) 23 | { 24 | unsigned char Sum=0; 25 | 26 | while (Size--) 27 | { 28 | Sum+=(*Buffer); 29 | Buffer++; 30 | } 31 | 32 | return (~Sum)+1; 33 | } 34 | 35 | static 36 | unsigned char 37 | ValidateModule100(unsigned char *Buffer, UINT32 Size) 38 | { 39 | unsigned char Sum=0; 40 | 41 | while (Size--) 42 | { 43 | Sum+=(*Buffer); 44 | Buffer++; 45 | } 46 | 47 | return Sum; 48 | } 49 | 50 | static 51 | FMH * 52 | CheckForNormalFMH(FMH *fmh) 53 | { 54 | if (strncmp((char *)fmh->FMH_Signature,FMH_SIGNATURE,sizeof(FMH_SIGNATURE)-1) != 0) 55 | return NULL; 56 | 57 | if (le16_to_host(fmh->FMH_End_Signature) != FMH_END_SIGNATURE) 58 | return NULL; 59 | 60 | if (ValidateModule100((unsigned char *)fmh,sizeof(FMH)) != 0) 61 | return NULL; 62 | 63 | return fmh; 64 | 65 | } 66 | 67 | static 68 | UINT32 69 | CheckForAlternateFMH(ALT_FMH *altfmh) 70 | { 71 | 72 | if (strncmp((char *)altfmh->FMH_Signature,FMH_SIGNATURE,sizeof(FMH_SIGNATURE)-1) != 0) 73 | return INVALID_FMH_OFFSET; 74 | 75 | if (le16_to_host(altfmh->FMH_End_Signature) != FMH_END_SIGNATURE) 76 | return INVALID_FMH_OFFSET; 77 | 78 | if (ValidateModule100((unsigned char *)altfmh,sizeof(ALT_FMH)) != 0) 79 | return INVALID_FMH_OFFSET; 80 | 81 | return le32_to_host(altfmh->FMH_Link_Address); 82 | 83 | } 84 | 85 | FMH * 86 | ScanforFMH(unsigned char *SectorAddr, UINT32 SectorSize) 87 | { 88 | FMH *fmh; 89 | ALT_FMH *altfmh; 90 | UINT32 FMH_Offset; 91 | 92 | /* Check if Normal FMH is found */ 93 | fmh = (FMH *)SectorAddr; 94 | fmh = CheckForNormalFMH(fmh); 95 | if (fmh != NULL) 96 | return fmh; 97 | 98 | /* If Normal FMH is not found, check for alternate FMH */ 99 | altfmh = (ALT_FMH *)(SectorAddr+SectorSize - sizeof(ALT_FMH)); 100 | FMH_Offset = CheckForAlternateFMH(altfmh); 101 | if (FMH_Offset == INVALID_FMH_OFFSET) 102 | return NULL; 103 | fmh = (FMH *)(SectorAddr +FMH_Offset); 104 | 105 | /* If alternate FMH is found, validate it */ 106 | fmh = CheckForNormalFMH(fmh); 107 | return fmh; 108 | } 109 | 110 | void 111 | CreateFMH(FMH *fmh,UINT32 AllocatedSize, MODULE_INFO *mod, UINT32 Location) 112 | { 113 | /* Clear the Structure */ 114 | memset((void *)fmh,0,sizeof(FMH)); 115 | 116 | /* Copy the module information */ 117 | memcpy((void *)&(fmh->Module_Info),(void *)mod,sizeof(MODULE_INFO)); 118 | 119 | /* Fill the FMH Fields */ 120 | strncpy((char *)fmh->FMH_Signature,FMH_SIGNATURE,sizeof(FMH_SIGNATURE)-1); 121 | fmh->FMH_Ver_Major = FMH_MAJOR; 122 | fmh->FMH_Ver_Minor = FMH_MINOR; 123 | fmh->FMH_Size = FMH_SIZE; 124 | fmh->FMH_End_Signature = host_to_le16(FMH_END_SIGNATURE); 125 | 126 | fmh->FMH_AllocatedSize = host_to_le32(AllocatedSize); 127 | fmh-> FMH_Location = host_to_le32(Location); 128 | 129 | /*Calculate Header Checksum*/ 130 | fmh->FMH_Header_Checksum = CalculateModule100((unsigned char *)fmh,sizeof(FMH)); 131 | 132 | return; 133 | } 134 | 135 | void 136 | CreateAlternateFMH(ALT_FMH *altfmh,UINT32 FMH_Offset) 137 | { 138 | /* Clear the Structure */ 139 | memset((void *)altfmh,0,sizeof(ALT_FMH)); 140 | 141 | /* Fill the FMH Fields */ 142 | strncpy((char *)altfmh->FMH_Signature,FMH_SIGNATURE,sizeof(FMH_SIGNATURE)-1); 143 | altfmh->FMH_End_Signature = host_to_le16(FMH_END_SIGNATURE); 144 | 145 | altfmh->FMH_Link_Address = host_to_le32(FMH_Offset); 146 | 147 | /*Calculate Header Checksum*/ 148 | altfmh->FMH_Header_Checksum = CalculateModule100((unsigned char *)altfmh, 149 | sizeof(ALT_FMH)); 150 | return; 151 | } 152 | 153 | 154 | 155 | UINT32 156 | CalculateCRC32(unsigned char *Buffer, UINT32 Size) 157 | { 158 | UINT32 i,crc32 = 0xFFFFFFFF; 159 | 160 | /* Read the data and calculate crc32 */ 161 | for(i = 0; i < Size; i++) 162 | crc32 = ((crc32) >> 8) ^ CrcLookUpTable[(Buffer[i]) 163 | ^ ((crc32) & 0x000000FF)]; 164 | return ~crc32; 165 | } 166 | 167 | void 168 | BeginCRC32(UINT32 *crc32) 169 | { 170 | *crc32 = 0xFFFFFFFF; 171 | return; 172 | } 173 | 174 | void 175 | DoCRC32(UINT32 *crc32, unsigned char Data) 176 | { 177 | *crc32=((*crc32) >> 8) ^ CrcLookUpTable[Data ^ ((*crc32) & 0x000000FF)]; 178 | return; 179 | } 180 | 181 | void 182 | EndCRC32(UINT32 *crc32) 183 | { 184 | *crc32 = ~(*crc32); 185 | return; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /genimage/fwinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "fmh.h" 11 | #include "iniparser.h" 12 | 13 | #if RELEASE_NAME_REQUIRED 14 | #define RELEASE_FILENAME "/tmp/ReleaseFileName" 15 | #endif 16 | 17 | 18 | static 19 | char * 20 | GetOemKey(char **OemKeyName) 21 | { 22 | char *start = NULL; 23 | int keygot = 0; 24 | char *Key = *OemKeyName; 25 | 26 | if (*OemKeyName == NULL) 27 | return NULL; 28 | 29 | while (*Key != 0) 30 | { 31 | if ((*Key == ' ') || (*Key == '\t') || (*Key == ',')) 32 | { 33 | if (keygot) 34 | { 35 | *OemKeyName = Key+1; 36 | *Key = 0; 37 | return start; 38 | } 39 | } 40 | else 41 | { 42 | if (!keygot) 43 | { 44 | keygot = 1; 45 | start = Key; 46 | } 47 | } 48 | Key++; 49 | } 50 | 51 | if (*Key == 0) 52 | *OemKeyName = 0; 53 | 54 | return start; 55 | } 56 | 57 | 58 | 59 | UINT32 60 | CreateFirmwareInfo(unsigned char *Data, char * BuildFile, 61 | unsigned char Major,unsigned char Minor,dictionary *d) 62 | { 63 | unsigned int BuildNo; 64 | unsigned long ProductId; 65 | char *ProductName; 66 | UINT32 len = 0; 67 | unsigned char *Desc; 68 | FILE *Buildfd; 69 | #if RELEASE_NAME_REQUIRED 70 | unsigned char *ProjName; 71 | FILE *ReleaseFd; 72 | time_t tim; 73 | struct tm *tm; 74 | #endif 75 | 76 | /* Oem Extensions */ 77 | char Key[80]; 78 | char *OemKeys, *OemKeyName,*OemKeyValue,*Next; 79 | char OemKeyStr[128]; 80 | 81 | 82 | /* Get BUILD NO if specificed in config, else try to get from BUILDNO */ 83 | BuildNo = iniparser_getlong(d,"GLOBAL:BuildNo",0); 84 | if (BuildNo == 0) 85 | { 86 | /* Open Module File */ 87 | Buildfd = fopen(BuildFile,"rb"); 88 | if (Buildfd == NULL) 89 | { 90 | printf("WARNING: Unable to get the Build File of Firmware\n"); 91 | BuildNo = 0; 92 | } 93 | else 94 | { 95 | if (fscanf(Buildfd,"%u",&BuildNo) != 1) 96 | { 97 | printf("WARNING: Unable to get the Build Number of Firmware\n"); 98 | BuildNo = 0; 99 | } 100 | fclose(Buildfd); 101 | } 102 | } 103 | 104 | len +=sprintf((char *)Data+len,"FW_VERSION=%d.%d.%d\n",Major,Minor,BuildNo); 105 | len +=sprintf((char *)Data+len,"FW_DATE=%s\n",__DATE__); 106 | len +=sprintf((char *)Data+len,"FW_BUILDTIME=%s\n",__TIME__); 107 | 108 | Desc = (unsigned char *)getenv("FW_DESC"); 109 | if (Desc != NULL) 110 | len +=sprintf((char *)Data+len,"FW_DESC=%s\n",Desc); 111 | else 112 | len +=sprintf((char *)Data+len,"FW_DESC=WARNING : UNOFFICIAL BUILD!! \n"); 113 | 114 | ProductId = iniparser_getlong(d,"GLOBAL:ProductId",0); 115 | if (ProductId != 0) 116 | len +=sprintf((char *)Data+len,"FW_PRODUCTID=%ld\n",ProductId); 117 | ProductName = iniparser_getstr(d,"GLOBAL:ProductName"); 118 | if (ProductName != NULL) 119 | len +=sprintf((char *)Data+len,"FW_PRODUCTNAME=%s\n",ProductName); 120 | 121 | /* Oem Extensions if any */ 122 | OemKeys = iniparser_getstr(d,"GLOBAL:Oemkeys"); 123 | if (OemKeys != NULL) 124 | { 125 | strncpy(OemKeyStr,OemKeys,127); 126 | OemKeyStr[127]=0; 127 | OemKeyName=&OemKeyStr[0]; 128 | 129 | Next = OemKeyName; 130 | OemKeyName = GetOemKey(&Next); 131 | while (OemKeyName != NULL) 132 | { 133 | sprintf(Key,"GLOBAL:%s",OemKeyName); 134 | OemKeyValue = iniparser_getstr(d,Key); 135 | if (OemKeyValue!= NULL) 136 | len +=sprintf((char *)Data+len,"OEM_%s=%s\n",OemKeyName,OemKeyValue); 137 | OemKeyName = GetOemKey(&Next); 138 | 139 | } 140 | } 141 | 142 | #if RELEASE_NAME_REQUIRED 143 | /* For Official Build Create Output file with detailed name */ 144 | unlink(RELEASE_FILENAME); 145 | 146 | if (Desc == NULL) 147 | return len; 148 | 149 | /* Get the Project Name */ 150 | ProjName = (unsigned char *)getenv("RACTRENDS_PROJECT"); 151 | if (ProjName == NULL) 152 | return len; 153 | 154 | /* Get Current Date and Time */ 155 | time(&tim); 156 | tm = localtime(&tim); 157 | 158 | /* Write the name to file */ 159 | ReleaseFd =fopen(RELEASE_FILENAME,"wt"); 160 | if (ReleaseFd != NULL) 161 | { 162 | fprintf(ReleaseFd,"%sfw-%d.%d.%d-%02d%02d%04d.ima",ProjName, 163 | Major,Minor,BuildNo, 164 | tm->tm_mon+1,tm->tm_mday,tm->tm_year+1900); 165 | fclose(ReleaseFd); 166 | } 167 | #endif 168 | 169 | return len; 170 | } 171 | 172 | -------------------------------------------------------------------------------- /genimage/genimage.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "iniparser.h" 13 | #include "fmh.h" 14 | 15 | typedef struct sc 16 | { 17 | char Name[9]; 18 | UINT32 Loc; 19 | UINT32 Size; 20 | unsigned char Major; 21 | unsigned char Minor; 22 | struct sc *Next; 23 | } SECTION_CHAIN; 24 | 25 | unsigned char FirmwareInfo[64*1024]; 26 | 27 | int ParseIniFile(char * ini_name); 28 | UINT32 FillModuleInfo(MODULE_INFO *Mod,char *InFile); 29 | int WriteFMHtoFile(FILE *fd,FMH *fmh,ALT_FMH *altfmh,UINT32 Start, 30 | UINT32 BlockSize); 31 | int WriteModuletoFile(FILE *Outfd,char *InFile, UINT32 Location); 32 | int WriteFirmwareInfo(FILE *Outfd,char *Data,UINT32 Size, UINT32 Location); 33 | int CalculateImageChecksum(FILE* fd,unsigned long ImageHeaderStart); 34 | 35 | extern UINT32 CreateFirmwareInfo(unsigned char *Data, char *BuildFile, 36 | unsigned char Major, unsigned char Minor,dictionary *d); 37 | 38 | extern unsigned char CalculateModule100(unsigned char *Buffer, unsigned long Size); 39 | static char CmdInDir[256]; 40 | static char CmdOutDir[256]; 41 | static char CmdCfgFile[256]; 42 | 43 | static unsigned long gBlkSize; 44 | 45 | /* Assumption: We are using only one FilePath and so we assume that 46 | * two parallel calls to Convert2FullPath will not be called. Other 47 | * wise only the last call will have a valid FilePath and the previous 48 | * ones will be destroyed */ 49 | char FilePath[256]; 50 | 51 | char * 52 | Convert2FullPath(char *Dir, char *FileName) 53 | { 54 | int len; 55 | 56 | /* No Path or Path is empty */ 57 | if (Dir == NULL) 58 | return FileName; 59 | if (strlen(Dir) == 0) 60 | return FileName; 61 | 62 | /* Check if path is given in FileName */ 63 | if (strchr(FileName,'/') != NULL) 64 | return FileName; 65 | 66 | /* Copy the directory to path */ 67 | strcpy(&FilePath[0],Dir); 68 | 69 | /* If last char of path is not /, append a / */ 70 | len = strlen(FilePath); 71 | if (FilePath[len-1] != '/') 72 | strcat(FilePath,"/"); 73 | 74 | /* Append the File Name */ 75 | strcat(FilePath,FileName); 76 | 77 | return FilePath; 78 | } 79 | 80 | static 81 | void 82 | Usage(char *Prog) 83 | { 84 | printf("Usage is %s \n",Prog); 85 | printf("Args are :\n"); 86 | printf("\t -I Input Files Path\n"); 87 | printf("\t -O Output Files Path\n"); 88 | printf("\t -C Config File Name\n"); 89 | printf("\n"); 90 | } 91 | 92 | int 93 | main(int argc, char * argv[]) 94 | { 95 | int status; 96 | int opt; 97 | char *ProgName; 98 | 99 | /* Skip Program Name */ 100 | ProgName = argv[0]; 101 | 102 | /* Initialize with empty values */ 103 | CmdInDir[0] = CmdOutDir[0] = CmdCfgFile[0] = 0; 104 | 105 | while ((opt = getopt(argc, argv, "i:o:c:h")) != -1) 106 | { 107 | switch (opt) 108 | { 109 | case 'i': 110 | strcpy(CmdInDir, optarg); 111 | break; 112 | case 'o': 113 | strcpy(CmdOutDir, optarg); 114 | break; 115 | case 'c': 116 | strcpy(CmdCfgFile, optarg); 117 | break; 118 | default: 119 | Usage(ProgName); 120 | exit(1); 121 | } 122 | } 123 | 124 | if (CmdCfgFile[0] != 0) 125 | status = ParseIniFile(CmdCfgFile); 126 | else 127 | status = ParseIniFile("genimage.ini"); 128 | 129 | return status ; 130 | } 131 | 132 | void 133 | DisplayFlashMap(SECTION_CHAIN *Chain, UINT32 FlashSize) 134 | { 135 | UINT32 Loc = 0; 136 | 137 | printf("\n"); 138 | printf("-----------------------------------------------\n"); 139 | printf(" Flash Memory Map \n"); 140 | printf("-----------------------------------------------\n"); 141 | while (Chain) 142 | { 143 | if (Chain->Loc > Loc) 144 | printf("0x%07lX - 0x%07lX : *******FREE*******\n",Loc, Chain->Loc); 145 | printf("0x%07lX - 0x%07lX : %8s : Ver %d.%d\n",Chain->Loc,Chain->Loc+Chain->Size,Chain->Name, Chain->Major,Chain->Minor); 146 | 147 | Loc = Chain->Loc+Chain->Size; 148 | Chain = Chain->Next; 149 | } 150 | 151 | if (Loc < FlashSize) 152 | printf("0x%07lX - 0x%07lX : *******FREE*******\n",Loc, FlashSize); 153 | printf("-----------------------------------------------\n"); 154 | return; 155 | } 156 | 157 | int 158 | AddToUsedChain(SECTION_CHAIN **pChain,UINT32 Loc, UINT32 Size, char *Name, 159 | unsigned char Major,unsigned char Minor) 160 | { 161 | SECTION_CHAIN *newchain, *Prev; 162 | SECTION_CHAIN *Chain = *pChain; 163 | 164 | /* Allocate memory for new entry */ 165 | newchain = (SECTION_CHAIN *)malloc(sizeof(SECTION_CHAIN)); 166 | if (newchain == NULL) 167 | { 168 | printf("INTERNAL ERROR: Unable to allocate memory for Chain\n"); 169 | return 1; 170 | } 171 | 172 | /* Fill the Entries */ 173 | newchain->Loc = Loc; 174 | newchain->Size = Size; 175 | newchain->Major = Major; 176 | newchain->Minor = Minor; 177 | strncpy(&(newchain->Name[0]),Name,8); 178 | newchain->Name[8] = 0; 179 | newchain->Next = NULL; 180 | 181 | 182 | /* If first entry */ 183 | if (Chain == NULL) 184 | { 185 | *pChain = newchain; 186 | return 0; 187 | } 188 | 189 | /* Traverse chain to find the right spot */ 190 | Prev = NULL; 191 | while (Chain) 192 | { 193 | /* Check if overlaps exactly on other section */ 194 | if (Loc == Chain->Loc) 195 | { 196 | printf("ERROR: Section %s overlaps with Section %s\n",Name,Chain->Name); 197 | return 2; 198 | } 199 | 200 | /* If our start is below the current entry */ 201 | if (Loc < Chain->Loc) 202 | { 203 | /* Check if our section's end overlaps with current section */ 204 | if ((Loc+Size) > Chain->Loc) 205 | { 206 | printf("ERROR: Section %s overlaps with Section %s\n",Name,Chain->Name); 207 | return 2; 208 | } 209 | 210 | /* We got our spot !!*/ 211 | break; 212 | } 213 | 214 | /* If our start is above the current entry*/ 215 | if (Loc > Chain->Loc) 216 | { 217 | /* Check if our section's begin overlaps with the current section */ 218 | if (Loc < (Chain->Loc + Chain->Size)) 219 | { 220 | printf("ERROR: Section %s overlaps with Section %s\n",Name,Chain->Name); 221 | return 2; 222 | } 223 | } 224 | 225 | /* We are well above the current entry. So Continue with the chain traverse */ 226 | Prev = Chain; 227 | Chain = Chain->Next; 228 | } 229 | 230 | /* If new entry is to be added to first of chain */ 231 | if (Prev == NULL) 232 | { 233 | newchain->Next = *pChain; 234 | *pChain = newchain; 235 | return 0; 236 | } 237 | 238 | /* Add to Middle or last of chain */ 239 | newchain->Next = Prev->Next; 240 | Prev->Next = newchain; 241 | return 0; 242 | } 243 | 244 | 245 | int 246 | ParseIniFile(char* ini_name) 247 | { 248 | /* INI Parser Related */ 249 | dictionary *d; /* Dictionary */ 250 | int nsecs,i; /* Number of Sections */ 251 | char Key[80]; /* To Form the Key to be passed to ini functions */ 252 | char *SecName; /* Section Name */ 253 | 254 | /* Global Information */ 255 | char *OutFile; /* Output Bin File */ 256 | INT32 FlashSize; /* Size of Flash */ 257 | INT32 BlockSize; /* Size of each Flash Block */ 258 | char *InDir; /* Location of Input Files */ 259 | char *OutDir; /* Location of Output File */ 260 | 261 | /* Output File Creation Related */ 262 | FILE *Outfd; /* Output File Descriptor */ 263 | UINT32 Erase; /* Dummy char used to create the output file */ 264 | SECTION_CHAIN *UsedChain;/* Used for checking overlapping sections */ 265 | 266 | /* FMH Related */ 267 | FMH fmh; /* Flash Module Header */ 268 | ALT_FMH altfmh,*paltfmh; /* Alternate Flash Module Header */ 269 | MODULE_INFO mod; /* Module Information */ 270 | char *InFile; /* Input File for FMH Section */ 271 | UINT32 InFileSize; /* Size of Section File */ 272 | UINT32 AllocSize;/* Total Allocation Size for this FMH */ 273 | UINT32 MinAllocSize;/* Mininmum Calculated Allocation Size */ 274 | UINT32 FMHLoc; /* Alternate FMH Location */ 275 | char *LocationStr; /* Flash Location String */ 276 | UINT32 Location; /* Flash Location Value */ 277 | 278 | /* RACTRENDS releted */ 279 | char *BuildFile; /* Build Number File */ 280 | char *VersionStr; /* Major and Minor String */ 281 | int FirmwareMajor,FirmwareMinor; 282 | unsigned char ModuleFormat; 283 | unsigned long ImageHeaderStart = 0xFFFFFFFF; /* This points to the MODULE FIRMWARE start address */ 284 | int UseFMH=1; 285 | 286 | /*Load the ini File into dictionary*/ 287 | d = iniparser_load(ini_name); 288 | if (d==NULL) 289 | { 290 | printf("Error:Cannot parse file [%s]\n", ini_name); 291 | return 1 ; 292 | } 293 | #if DEBUG 294 | iniparser_dump(d, stderr); 295 | #endif 296 | 297 | 298 | /* Get the global information */ 299 | OutFile = iniparser_getstr(d,"GLOBAL:Output"); 300 | if (OutFile == NULL) 301 | { 302 | printf("Error: Unable to get Output file name\n"); 303 | iniparser_freedict(d); 304 | return 1; 305 | } 306 | FlashSize = iniparser_getlong(d,"GLOBAL:FlashSize",0); 307 | if (FlashSize == 0) 308 | { 309 | printf("Error: Unable to get Flash Size\n"); 310 | iniparser_freedict(d); 311 | return 1; 312 | } 313 | BlockSize = iniparser_getlong(d,"GLOBAL:BlockSize",0); 314 | gBlkSize = BlockSize; 315 | if (BlockSize == 0) 316 | { 317 | printf("Error: Unable to get Block Size\n"); 318 | iniparser_freedict(d); 319 | return 1; 320 | } 321 | 322 | UseFMH = iniparser_getlong(d,"GLOBAL:FMHEnable",1); 323 | printf("The Image file %s have FMH\n",UseFMH?"will":"will not"); 324 | 325 | /* Get the Input and Output Directory Path */ 326 | if (CmdOutDir[0] == 0) 327 | OutDir = iniparser_getstr(d,"GLOBAL:OutDir"); 328 | else 329 | OutDir = &CmdOutDir[0]; 330 | 331 | if (CmdInDir[0] == 0) 332 | InDir = iniparser_getstr(d,"GLOBAL:OutDir"); 333 | else 334 | InDir = &CmdInDir[0]; 335 | 336 | /* Convert OutputFile to Full Path */ 337 | OutFile = Convert2FullPath(OutDir,OutFile); 338 | 339 | printf("\nCreating \"%s\" ...\n",OutFile); 340 | printf("FlashSize = 0x%lx BlockSize = 0x%lx\n",FlashSize,BlockSize); 341 | 342 | /* Create and open the output file */ 343 | Outfd = fopen(OutFile,"w+b"); 344 | if (Outfd == NULL) 345 | { 346 | printf("Error: Unable to get Create Output file %s\n",OutFile); 347 | iniparser_freedict(d); 348 | return 1; 349 | } 350 | Erase = 0xFFFFFFFF; 351 | for (i=0;i 8) 378 | strncpy((char *)mod.Module_Name,SecName,8); 379 | else 380 | strcpy((char *)mod.Module_Name,SecName); 381 | 382 | /* Get Module Version */ 383 | sprintf(Key,"%s:Major",SecName); 384 | mod.Module_Ver_Major = iniparser_getint(d,Key,0); 385 | sprintf(Key,"%s:Minor",SecName); 386 | mod.Module_Ver_Minor = iniparser_getint(d,Key,0); 387 | 388 | /* Get Module Type */ 389 | sprintf(Key,"%s:Type",SecName); 390 | mod.Module_Type = iniparser_getint(d,Key,0x0000); 391 | ModuleFormat = (mod.Module_Type >> 8); 392 | 393 | /* Check if altFMH to be used */ 394 | sprintf(Key,"%s:FMHLoc",SecName); 395 | FMHLoc = iniparser_getlong(d,Key,0); 396 | /* Get Module Location . Default is 0x40 for normal section 397 | * and one block size for JFFS/JFFS2 */ 398 | sprintf(Key,"%s:Offset",SecName); 399 | /* If Alternate FMH to be used, offset will be 0 if not specified */ 400 | if (FMHLoc != 0) 401 | mod.Module_Location = iniparser_getlong(d,Key,0); 402 | else 403 | { 404 | if ((mod.Module_Type == MODULE_JFFS) || (mod.Module_Type == MODULE_JFFS2)|| 405 | (mod.Module_Type == MODULE_JFFS_CONFIG) || 406 | (mod.Module_Type == MODULE_JFFS2_CONFIG) || 407 | (ModuleFormat == MODULE_FORMAT_JFFS) || 408 | (ModuleFormat == MODULE_FORMAT_JFFS2)) 409 | mod.Module_Location = iniparser_getlong(d,Key,BlockSize); 410 | else 411 | mod.Module_Location = iniparser_getlong(d,Key,0x40); 412 | } 413 | if (!UseFMH) 414 | mod.Module_Location = 0; 415 | 416 | 417 | /* Get Flags */ 418 | sprintf(Key,"%s:BootOS",SecName); 419 | if (iniparser_getboolean(d,Key,0) == 1) 420 | mod.Module_Flags |= MODULE_FLAG_BOOTPATH_OS; 421 | sprintf(Key,"%s:BootDIAG",SecName); 422 | if (iniparser_getboolean(d,Key,0) == 1) 423 | mod.Module_Flags |= MODULE_FLAG_BOOTPATH_DIAG; 424 | sprintf(Key,"%s:BootRECO",SecName); 425 | if (iniparser_getboolean(d,Key,0) == 1) 426 | mod.Module_Flags |= MODULE_FLAG_BOOTPATH_RECOVERY; 427 | sprintf(Key,"%s:CopyToRAM",SecName); 428 | if (iniparser_getboolean(d,Key,0) == 1) 429 | mod.Module_Flags |= MODULE_FLAG_COPY_TO_RAM; 430 | sprintf(Key,"%s:Execute",SecName); 431 | if (iniparser_getboolean(d,Key,0) == 1) 432 | mod.Module_Flags |= MODULE_FLAG_EXECUTE; 433 | sprintf(Key,"%s:Checksum",SecName); 434 | if (iniparser_getboolean(d,Key,0) == 1) 435 | mod.Module_Flags |= MODULE_FLAG_VALID_CHECKSUM; 436 | sprintf(Key,"%s:Compress",SecName); 437 | mod.Module_Flags |= iniparser_getint(d,Key,0x00) 438 | << MODULE_FLAG_COMPRESSION_LSHIFT; 439 | 440 | /* Get Load Address */ 441 | sprintf(Key,"%s:Load",SecName); 442 | mod.Module_Load_Address = iniparser_getlong(d,Key,0xFFFFFFFF); 443 | if (mod.Module_Load_Address == 0xFFFFFFFF) 444 | mod.Module_Flags &= (~MODULE_FLAG_COPY_TO_RAM); 445 | 446 | /* Get Allocation Size */ 447 | sprintf(Key,"%s:Alloc",SecName); 448 | AllocSize = iniparser_getlong(d,Key,0); 449 | 450 | 451 | if ((mod.Module_Type == MODULE_FMH_FIRMWARE) || 452 | (mod.Module_Type == MODULE_FIRMWARE_1_4)) 453 | AllocSize = BlockSize; 454 | 455 | /* Module Firmware is a dummy section. It does not have any data */ 456 | if ((mod.Module_Type != MODULE_FMH_FIRMWARE) && 457 | (mod.Module_Type != MODULE_FIRMWARE_1_4)) 458 | { 459 | /* Check for mandatory Field - Input File Name */ 460 | sprintf(Key,"%s:File",SecName); 461 | InFile = iniparser_getstr(d,Key); 462 | if (InFile == NULL) 463 | { 464 | printf("ERROR: Unable to get Input file for Section %s\n",SecName); 465 | break; 466 | } 467 | 468 | /* Convert InputFile to Full Path */ 469 | InFile = Convert2FullPath(InDir,InFile); 470 | #if DEBUG 471 | printf("Input File = [%s]\n",InFile); 472 | #endif 473 | 474 | /* Fill the remaining Fields of MODULE_INFO - Size, Checksum*/ 475 | InFileSize = FillModuleInfo(&mod,InFile); 476 | if (InFileSize == 0) 477 | { 478 | printf("ERROR: Input file (%s) size for section %s is 0\n",InFile,SecName); 479 | break; 480 | } 481 | 482 | #if 0 483 | /* For JFFS and JFFS2, it should be a multiple of BlockSize */ 484 | /* Otherwise the mtd will be mounted read only */ 485 | if ((mod.Module_Type == MODULE_JFFS) || 486 | (mod.Module_Type == MODULE_JFFS2)) 487 | { 488 | InFileSize = (InFileSize+BlockSize-1); 489 | InFileSize = (InFileSize/BlockSize) * BlockSize; 490 | } 491 | #endif 492 | 493 | mod.Module_Size = InFileSize; 494 | 495 | /* Calculate the Min Allocation Size */ 496 | MinAllocSize = mod.Module_Location + InFileSize; 497 | MinAllocSize += (BlockSize-1); 498 | MinAllocSize = (MinAllocSize/BlockSize) * BlockSize; 499 | 500 | if (AllocSize != 0) 501 | { 502 | if (AllocSize < MinAllocSize) 503 | printf("WARNING: Section %s size exceeds the Allocated Size\n",SecName); 504 | } 505 | 506 | if (AllocSize < MinAllocSize) 507 | AllocSize = MinAllocSize; 508 | 509 | } 510 | else 511 | { 512 | /* Check if Firmware version is overridden by Build script */ 513 | VersionStr = getenv("FW_MAJOR"); 514 | if (VersionStr != NULL) 515 | { 516 | if (sscanf(VersionStr,"%d",&FirmwareMajor) == 1) 517 | mod.Module_Ver_Major = (unsigned char)FirmwareMajor; 518 | } 519 | 520 | VersionStr = getenv("FW_MINOR"); 521 | if (VersionStr != NULL) 522 | { 523 | if (sscanf(VersionStr,"%d",&FirmwareMinor) == 1) 524 | mod.Module_Ver_Minor = (unsigned char)FirmwareMinor; 525 | } 526 | 527 | /* For Ractrends Series Firmware Section has some vendor specific Info */ 528 | BuildFile = Convert2FullPath(OutDir,"BUILDNO"); 529 | mod.Module_Size = CreateFirmwareInfo(&FirmwareInfo[0],BuildFile, 530 | mod.Module_Ver_Major,mod.Module_Ver_Minor,d); 531 | 532 | if (mod.Module_Size > ((64*1024) - 0x40)) 533 | mod.Module_Size = 0; 534 | } 535 | 536 | /* Read Flash Location .It can be either START or END or numeric value */ 537 | Location = 0xFFFFFFFF; 538 | sprintf(Key,"%s:Locate",SecName); 539 | LocationStr = iniparser_getstr(d,Key); 540 | if (LocationStr == NULL) 541 | { 542 | printf("ERROR: Unable to get Module Location in Flash for %s\n",SecName); 543 | break; 544 | } 545 | if (strcasecmp(LocationStr,"START") == 0) 546 | Location = 0; 547 | if (strcasecmp(LocationStr,"END") == 0) 548 | Location = FlashSize-AllocSize; 549 | if (Location == 0xFFFFFFFF) 550 | { 551 | Location = iniparser_getlong(d,Key,0xFFFFFFFF); 552 | if (Location == 0xFFFFFFFF) 553 | { 554 | printf("ERROR: Unable to get Module Location in Flash for %s\n",SecName); 555 | break; 556 | } 557 | } 558 | 559 | /* Validate Location */ 560 | if ((Location > FlashSize) || (Location+AllocSize > FlashSize)) 561 | { 562 | printf("ERROR: Module Location %ld, Alloc %ld, > Flash %ld for %s\n", 563 | Location,AllocSize,FlashSize,SecName); 564 | break; 565 | } 566 | 567 | /* Check for overlapping sections and add location and size 568 | * and section name to the chain of used areas */ 569 | if (AddToUsedChain(&UsedChain,Location,AllocSize,SecName, 570 | mod.Module_Ver_Major,mod.Module_Ver_Minor) != 0) 571 | break; 572 | 573 | /* Create FMH and Alternate FMH if required */ 574 | CreateFMH(&fmh,AllocSize,&mod,Location+FMHLoc); 575 | if ((mod.Module_Type == MODULE_FMH_FIRMWARE) || 576 | (mod.Module_Type == MODULE_FIRMWARE_1_4)) 577 | { 578 | fmh.FMH_Header_Checksum = 0x00; 579 | ImageHeaderStart = Location; 580 | } 581 | paltfmh = NULL; 582 | if (FMHLoc != 0) 583 | { 584 | printf("%s: Alternate location @ 0x%lx\n",SecName,FMHLoc); 585 | CreateAlternateFMH(&altfmh,FMHLoc); 586 | paltfmh = &altfmh; 587 | } 588 | 589 | 590 | if ((mod.Module_Type != MODULE_FMH_FIRMWARE) && 591 | (mod.Module_Type != MODULE_FIRMWARE_1_4)) 592 | { 593 | if (WriteModuletoFile(Outfd,InFile,Location+mod.Module_Location)!= 0) 594 | { 595 | printf("ERROR: Unable to Write Module of Section %s\n",SecName); 596 | break; 597 | } 598 | } 599 | else 600 | { 601 | if (mod.Module_Size > 0) 602 | { 603 | if (WriteFirmwareInfo(Outfd,(char *)FirmwareInfo,mod.Module_Size, 604 | Location+mod.Module_Location)!= 0) 605 | { 606 | printf("ERROR: Unable to Write Firmware Info in Section %s\n",SecName); break; 607 | } 608 | } 609 | else 610 | printf("INFO: No Firmware Information written to FIRMWARE Section\n"); 611 | } 612 | 613 | // Write FMH/ALTFMH after Module is written 614 | /* Write the FMH to output file */ 615 | if (UseFMH) 616 | { 617 | if (WriteFMHtoFile(Outfd,&fmh,paltfmh,Location,BlockSize) != 0) 618 | { 619 | printf("ERROR: Unable to Write FMH of Section %s\n",SecName); 620 | break; 621 | } 622 | } 623 | 624 | } 625 | /* Calculate complete image checksum now and fill in the MODULE INFO checksum field */ 626 | if (ImageHeaderStart != 0xFFFFFFFF) 627 | { 628 | if(CalculateImageChecksum(Outfd,ImageHeaderStart) == 0) 629 | printf("ERROR: Image Checksum calculation failed\n"); 630 | } 631 | 632 | /* Close the Output File */ 633 | fclose(Outfd); 634 | 635 | /* Free the Dictionary */ 636 | iniparser_freedict(d); 637 | 638 | /* Display the allocated and free regions of Flash */ 639 | if (i == nsecs) 640 | { 641 | printf("Flash Image created Successfully!\n"); 642 | DisplayFlashMap(UsedChain,FlashSize); 643 | return 0; 644 | } 645 | return 1; 646 | } 647 | 648 | UINT32 649 | FillModuleInfo(MODULE_INFO *mod,char *InFile) 650 | { 651 | struct stat InStat; 652 | UINT32 FileSize; 653 | UINT32 i,crc32; 654 | int fd; 655 | unsigned char data; 656 | 657 | 658 | /* Get the Module File Size */ 659 | if (stat(InFile,&InStat) != 0) 660 | return 0; /* Error in stat. Possibly a bad file */ 661 | FileSize = InStat.st_size; 662 | 663 | /* Open the File for crc32 calculation */ 664 | fd = open(InFile,O_RDONLY); 665 | if (fd < 0) 666 | return 0; 667 | 668 | /* Read the data and calculate crc32 */ 669 | BeginCRC32(&crc32); 670 | for(i = 0; i < FileSize; i++) 671 | { 672 | if (read(fd,&data,1) != 1) 673 | { 674 | close(fd); 675 | return 0; 676 | } 677 | DoCRC32(&crc32,data); 678 | } 679 | EndCRC32(&crc32); 680 | close(fd); 681 | 682 | /* Fill Module Checksum */ 683 | mod->Module_Checksum = crc32; 684 | 685 | 686 | /* Return Module Size */ 687 | return FileSize; 688 | } 689 | 690 | int 691 | WriteFMHtoFile(FILE *fd,FMH *fmh,ALT_FMH *altfmh,UINT32 Start, 692 | UINT32 BlockSize) 693 | { 694 | UINT32 offset = 0; 695 | 696 | if (altfmh != NULL) 697 | offset = altfmh->FMH_Link_Address; 698 | 699 | /* Write FMH Header */ 700 | if (fseek(fd,Start+offset,SEEK_SET) != 0) 701 | { 702 | printf("ERROR:Unable to seek %ld for FMH Header\n",Start+offset); 703 | return 1; 704 | } 705 | if (fwrite((void *)fmh,sizeof(FMH),1,fd) != 1) 706 | { 707 | printf("ERROR:Unable to write FMH Header\n"); 708 | return 1; 709 | } 710 | 711 | /* Write Alternate FMH Header */ 712 | if (altfmh != NULL) 713 | { 714 | offset = BlockSize - sizeof(ALT_FMH); 715 | if (fseek(fd,Start+offset,SEEK_SET) != 0) 716 | { 717 | printf("ERROR:Unable to seek %ld for ALTFMH Header\n",Start+offset); 718 | return 1; 719 | } 720 | if (fwrite((void *)altfmh,sizeof(ALT_FMH),1,fd) != 1) 721 | { 722 | printf("ERROR:Unable to write ALTFMH Header\n"); 723 | return 1; 724 | } 725 | } 726 | 727 | return 0; 728 | } 729 | 730 | int 731 | WriteModuletoFile(FILE *Outfd,char *InFile, UINT32 Location) 732 | { 733 | int Infd; 734 | char data; 735 | 736 | /* Open Module File */ 737 | Infd = open(InFile,O_RDONLY); 738 | if (Infd < 0) 739 | return 1; 740 | 741 | /* Seek Output File */ 742 | if (fseek(Outfd,Location,SEEK_SET) != 0) 743 | { 744 | printf("ERROR:Unable to seek %ld for Module\n",Location); 745 | close(Infd); 746 | return 1; 747 | } 748 | 749 | while (1) 750 | { 751 | if (read(Infd,&data,1) != 1) 752 | break; 753 | if (fwrite((void *)&data,1,1,Outfd) != 1) 754 | { 755 | // printf("ERROR:Unable to write Module \n"); 756 | return 1; 757 | } 758 | } 759 | return 0; 760 | } 761 | 762 | int 763 | WriteFirmwareInfo(FILE *Outfd,char *Data,UINT32 Size, UINT32 Location) 764 | { 765 | /* Seek Output File */ 766 | if (fseek(Outfd,Location,SEEK_SET) != 0) 767 | { 768 | printf("ERROR:Unable to seek %ld for Module\n",Location); 769 | return 1; 770 | } 771 | 772 | /* Write Data */ 773 | if (fwrite((void *)Data,Size,1,Outfd) != 1) 774 | { 775 | // printf("ERROR:Unable to write Module\n"); 776 | return 1; 777 | } 778 | return 0; 779 | } 780 | int CalculateImageChecksum(FILE* fd,unsigned long ImageHeaderStart) 781 | { 782 | unsigned long FileSize; 783 | unsigned long i,crc32; 784 | unsigned char data; 785 | unsigned char Buffer[128]; 786 | unsigned char Mod100Checksum = 0; 787 | 788 | 789 | /* We want to calculate the checksum until the end of FIRMWARE MODULE section. */ 790 | FileSize = ImageHeaderStart+gBlkSize; 791 | printf("FileSize = 0x%lX\n",FileSize); 792 | 793 | /* Rewind file to make sure that it's at the begining */ 794 | rewind(fd); 795 | /* Read the data and calculate crc32 */ 796 | BeginCRC32(&crc32); 797 | for(i = 0; i < FileSize; i++) 798 | { 799 | if (fread(&data,sizeof(unsigned char),1,fd) != 1) 800 | { 801 | printf("ERROR: fread failed while reading image to calculate checksum\n"); 802 | return 0; 803 | } 804 | if((i >= (ImageHeaderStart+FMH_MODULE_CHECKSUM_START_OFFSET) && i <= (ImageHeaderStart+FMH_MODULE_CHCKSUM_END_OFFSET)) || (i == (ImageHeaderStart+FMH_FMH_HEADER_CHECKSUM_OFFSET))) 805 | continue; 806 | DoCRC32(&crc32,data); 807 | } 808 | EndCRC32(&crc32); 809 | crc32 = host_to_le32(crc32); 810 | printf("Image checksum is 0x%lX\n",crc32); 811 | /* Fill this image checksum in Module Checksum field of MODULE FIRMWARE */ 812 | fseek(fd,ImageHeaderStart+FMH_MODULE_CHECKSUM_START_OFFSET,SEEK_SET); 813 | if(fwrite(&crc32,sizeof(unsigned long),1,fd) == 0) 814 | if(fwrite(&crc32,sizeof(unsigned long),1,fd) == 0) 815 | { 816 | printf("ERROR: fwrite failed while updating image checksum field\n"); 817 | return 0; 818 | } 819 | /* Update FMH Modulo100 checksum now */ 820 | /* Again, the assumption here is that the firmware module is at 821 | the begining (START) of the image. And also, that there's no alternate 822 | FMH header for firmware module */ 823 | fseek(fd,ImageHeaderStart,SEEK_SET); 824 | fread(Buffer,sizeof(unsigned char),sizeof(FMH),fd); 825 | Mod100Checksum = CalculateModule100(Buffer,sizeof(FMH)); 826 | //printf("Mod100 Checksum is 0x%X\n",Mod100Checksum); 827 | 828 | fseek(fd,ImageHeaderStart+FMH_FMH_HEADER_CHECKSUM_OFFSET,SEEK_SET); 829 | if(fwrite(&Mod100Checksum,sizeof(unsigned char),1,fd) == 0) 830 | { 831 | printf("ERROR: fwrite failed while updating FMH modulo checksum field\n"); 832 | return 0; 833 | } 834 | 835 | return 1; 836 | } 837 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2000 by Nicolas Devillard. 2 | Written by Nicolas Devillard. Not derived from licensed software. 3 | 4 | Permission is granted to anyone to use this software for any 5 | purpose on any computer system, and to redistribute it freely, 6 | subject to the following restrictions: 7 | 8 | 1. The author is not responsible for the consequences of use of 9 | this software, no matter how awful, even if they arise 10 | from defects in it. 11 | 12 | 2. The origin of this software must not be misrepresented, either 13 | by explicit claim or by omission. 14 | 15 | 3. Altered versions must be plainly marked as such, and must not 16 | be misrepresented as being the original software. 17 | 18 | 4. This notice may not be removed or altered. 19 | 20 | 21 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # iniparser Makefile 3 | # 4 | 5 | CC = gcc -m32 6 | CFLAGS = -O3 -Wall -g 7 | AR = ar 8 | ARFLAGS = rcv 9 | RM = rm -f 10 | 11 | # Implicit rules 12 | 13 | SUFFIXES = .o .c .h .a .so .sl 14 | 15 | COMPILE.c=$(CC) $(CFLAGS) -c 16 | .c.o: 17 | @(echo "compiling $< ...") 18 | @($(COMPILE.c) -o $@ $<) 19 | 20 | 21 | SRCS = src/iniparser.c \ 22 | src/dictionary.c \ 23 | src/strlib.c 24 | 25 | OBJS = $(SRCS:.c=.o) 26 | 27 | all: libini.a 28 | 29 | libini.a: $(OBJS) 30 | @($(AR) $(ARFLAGS) libini.a $(OBJS)) 31 | 32 | clean: 33 | @($(RM) $(OBJS) libini.a) 34 | 35 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/src/dictionary.c: -------------------------------------------------------------------------------- 1 | 2 | /*-------------------------------------------------------------------------*/ 3 | /** 4 | @file dictionary.c 5 | @author N. Devillard 6 | @date Aug 2000 7 | @version $Revision: 1.23 $ 8 | @brief Implements a dictionary for string variables. 9 | 10 | This module implements a simple dictionary object, i.e. a list 11 | of string/string associations. This object is useful to store e.g. 12 | informations retrieved from a configuration file (ini files). 13 | */ 14 | /*--------------------------------------------------------------------------*/ 15 | 16 | /* 17 | $Id: dictionary.c,v 1.23 2002/06/17 09:30:46 ndevilla Exp $ 18 | $Author: ndevilla $ 19 | $Date: 2002/06/17 09:30:46 $ 20 | $Revision: 1.23 $ 21 | */ 22 | 23 | /*--------------------------------------------------------------------------- 24 | Includes 25 | ---------------------------------------------------------------------------*/ 26 | 27 | #include "dictionary.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | /** Maximum value size for integers and doubles. */ 36 | #define MAXVALSZ 1024 37 | 38 | /** Minimal allocated number of entries in a dictionary */ 39 | #define DICTMINSZ 128 40 | 41 | /** Invalid key token */ 42 | #define DICT_INVALID_KEY ((char*)-1) 43 | 44 | 45 | /*--------------------------------------------------------------------------- 46 | Private functions 47 | ---------------------------------------------------------------------------*/ 48 | 49 | /* Doubles the allocated size associated to a pointer */ 50 | /* 'size' is the current allocated size. */ 51 | static void * mem_double(void * ptr, int size) 52 | { 53 | void * newptr ; 54 | 55 | newptr = calloc(2*size, 1); 56 | memcpy(newptr, ptr, size); 57 | free(ptr); 58 | return newptr ; 59 | } 60 | 61 | 62 | /*--------------------------------------------------------------------------- 63 | Function codes 64 | ---------------------------------------------------------------------------*/ 65 | 66 | /*-------------------------------------------------------------------------*/ 67 | /** 68 | @brief Compute the hash key for a string. 69 | @param key Character string to use for key. 70 | @return 1 unsigned int on at least 32 bits. 71 | 72 | This hash function has been taken from an Article in Dr Dobbs Journal. 73 | This is normally a collision-free function, distributing keys evenly. 74 | The key is stored anyway in the struct so that collision can be avoided 75 | by comparing the key itself in last resort. 76 | */ 77 | /*--------------------------------------------------------------------------*/ 78 | 79 | unsigned dictionary_hash(char * key) 80 | { 81 | int len ; 82 | unsigned hash ; 83 | int i ; 84 | 85 | len = strlen(key); 86 | for (hash=0, i=0 ; i>6) ; 90 | } 91 | hash += (hash <<3); 92 | hash ^= (hash >>11); 93 | hash += (hash <<15); 94 | return hash ; 95 | } 96 | 97 | 98 | /*-------------------------------------------------------------------------*/ 99 | /** 100 | @brief Create a new dictionary object. 101 | @param size Optional initial size of the dictionary. 102 | @return 1 newly allocated dictionary objet. 103 | 104 | This function allocates a new dictionary object of given size and returns 105 | it. If you do not know in advance (roughly) the number of entries in the 106 | dictionary, give size=0. 107 | */ 108 | /*--------------------------------------------------------------------------*/ 109 | 110 | dictionary * dictionary_new(int size) 111 | { 112 | dictionary * d ; 113 | 114 | /* If no size was specified, allocate space for DICTMINSZ */ 115 | if (sizesize = size ; 119 | d->val = calloc(size, sizeof(char*)); 120 | d->key = calloc(size, sizeof(char*)); 121 | d->hash = calloc(size, sizeof(unsigned)); 122 | return d ; 123 | } 124 | 125 | 126 | /*-------------------------------------------------------------------------*/ 127 | /** 128 | @brief Delete a dictionary object 129 | @param d dictionary object to deallocate. 130 | @return void 131 | 132 | Deallocate a dictionary object and all memory associated to it. 133 | */ 134 | /*--------------------------------------------------------------------------*/ 135 | 136 | void dictionary_del(dictionary * d) 137 | { 138 | int i ; 139 | 140 | if (d==NULL) return ; 141 | for (i=0 ; isize ; i++) { 142 | if (d->key[i]!=NULL) 143 | free(d->key[i]); 144 | if (d->val[i]!=NULL) 145 | free(d->val[i]); 146 | } 147 | free(d->val); 148 | free(d->key); 149 | free(d->hash); 150 | free(d); 151 | return ; 152 | } 153 | 154 | 155 | 156 | /*-------------------------------------------------------------------------*/ 157 | /** 158 | @brief Get a value from a dictionary. 159 | @param d dictionary object to search. 160 | @param key Key to look for in the dictionary. 161 | @param def Default value to return if key not found. 162 | @return 1 pointer to internally allocated character string. 163 | 164 | This function locates a key in a dictionary and returns a pointer to its 165 | value, or the passed 'def' pointer if no such key can be found in 166 | dictionary. The returned character pointer points to data internal to the 167 | dictionary object, you should not try to free it or modify it. 168 | */ 169 | /*--------------------------------------------------------------------------*/ 170 | char * dictionary_get(dictionary * d, char * key, char * def) 171 | { 172 | unsigned hash ; 173 | int i ; 174 | 175 | hash = dictionary_hash(key); 176 | for (i=0 ; isize ; i++) { 177 | if (d->key==NULL) 178 | continue ; 179 | /* Compare hash */ 180 | if (hash==d->hash[i]) { 181 | /* Compare string, to avoid hash collisions */ 182 | if (!strcmp(key, d->key[i])) { 183 | return d->val[i] ; 184 | } 185 | } 186 | } 187 | return def ; 188 | } 189 | 190 | /*-------------------------------------------------------------------------*/ 191 | /** 192 | @brief Get a value from a dictionary, as a char. 193 | @param d dictionary object to search. 194 | @param key Key to look for in the dictionary. 195 | @param def Default value for the key if not found. 196 | @return char 197 | 198 | This function locates a key in a dictionary using dictionary_get, 199 | and returns the first char of the found string. 200 | */ 201 | /*--------------------------------------------------------------------------*/ 202 | char dictionary_getchar(dictionary * d, char * key, char def) 203 | { 204 | char * v ; 205 | 206 | if ((v=dictionary_get(d,key,DICT_INVALID_KEY))==DICT_INVALID_KEY) { 207 | return def ; 208 | } else { 209 | return v[0] ; 210 | } 211 | } 212 | 213 | 214 | /*-------------------------------------------------------------------------*/ 215 | /** 216 | @brief Get a value from a dictionary, as an int. 217 | @param d dictionary object to search. 218 | @param key Key to look for in the dictionary. 219 | @param def Default value for the key if not found. 220 | @return int 221 | 222 | This function locates a key in a dictionary using dictionary_get, 223 | and applies atoi on it to return an int. If the value cannot be found 224 | in the dictionary, the default is returned. 225 | */ 226 | /*--------------------------------------------------------------------------*/ 227 | int dictionary_getint(dictionary * d, char * key, int def) 228 | { 229 | char * v ; 230 | 231 | if ((v=dictionary_get(d,key,DICT_INVALID_KEY))==DICT_INVALID_KEY) { 232 | return def ; 233 | } else { 234 | return atoi(v); 235 | } 236 | } 237 | 238 | /*-------------------------------------------------------------------------*/ 239 | /** 240 | @brief Get a value from a dictionary, as a double. 241 | @param d dictionary object to search. 242 | @param key Key to look for in the dictionary. 243 | @param def Default value for the key if not found. 244 | @return double 245 | 246 | This function locates a key in a dictionary using dictionary_get, 247 | and applies atof on it to return a double. If the value cannot be found 248 | in the dictionary, the default is returned. 249 | */ 250 | /*--------------------------------------------------------------------------*/ 251 | double dictionary_getdouble(dictionary * d, char * key, double def) 252 | { 253 | char * v ; 254 | 255 | if ((v=dictionary_get(d,key,DICT_INVALID_KEY))==DICT_INVALID_KEY) { 256 | return def ; 257 | } else { 258 | return atof(v); 259 | } 260 | } 261 | 262 | 263 | /*-------------------------------------------------------------------------*/ 264 | /** 265 | @brief Set a value in a dictionary. 266 | @param d dictionary object to modify. 267 | @param key Key to modify or add. 268 | @param val Value to add. 269 | @return void 270 | 271 | If the given key is found in the dictionary, the associated value is 272 | replaced by the provided one. If the key cannot be found in the 273 | dictionary, it is added to it. 274 | 275 | It is Ok to provide a NULL value for val, but NULL values for the dictionary 276 | or the key are considered as errors: the function will return immediately 277 | in such a case. 278 | 279 | Notice that if you dictionary_set a variable to NULL, a call to 280 | dictionary_get will return a NULL value: the variable will be found, and 281 | its value (NULL) is returned. In other words, setting the variable 282 | content to NULL is equivalent to deleting the variable from the 283 | dictionary. It is not possible (in this implementation) to have a key in 284 | the dictionary without value. 285 | */ 286 | /*--------------------------------------------------------------------------*/ 287 | 288 | void dictionary_set(dictionary * d, char * key, char * val) 289 | { 290 | int i ; 291 | unsigned hash ; 292 | 293 | if (d==NULL || key==NULL) return ; 294 | 295 | /* Compute hash for this key */ 296 | hash = dictionary_hash(key) ; 297 | /* Find if value is already in blackboard */ 298 | if (d->n>0) { 299 | for (i=0 ; isize ; i++) { 300 | if (d->key[i]==NULL) 301 | continue ; 302 | if (hash==d->hash[i]) { /* Same hash value */ 303 | if (!strcmp(key, d->key[i])) { /* Same key */ 304 | /* Found a value: modify and return */ 305 | if (d->val[i]!=NULL) 306 | free(d->val[i]); 307 | d->val[i] = val ? strdup(val) : NULL ; 308 | /* Value has been modified: return */ 309 | return ; 310 | } 311 | } 312 | } 313 | } 314 | /* Add a new value */ 315 | /* See if dictionary needs to grow */ 316 | if (d->n==d->size) { 317 | 318 | /* Reached maximum size: reallocate blackboard */ 319 | d->val = mem_double(d->val, d->size * sizeof(char*)) ; 320 | d->key = mem_double(d->key, d->size * sizeof(char*)) ; 321 | d->hash = mem_double(d->hash, d->size * sizeof(unsigned)) ; 322 | 323 | /* Double size */ 324 | d->size *= 2 ; 325 | } 326 | 327 | /* Insert key in the first empty slot */ 328 | for (i=0 ; isize ; i++) { 329 | if (d->key[i]==NULL) { 330 | /* Add key here */ 331 | break ; 332 | } 333 | } 334 | /* Copy key */ 335 | d->key[i] = strdup(key); 336 | d->val[i] = val ? strdup(val) : NULL ; 337 | d->hash[i] = hash; 338 | d->n ++ ; 339 | return ; 340 | } 341 | 342 | /*-------------------------------------------------------------------------*/ 343 | /** 344 | @brief Delete a key in a dictionary 345 | @param d dictionary object to modify. 346 | @param key Key to remove. 347 | @return void 348 | 349 | This function deletes a key in a dictionary. Nothing is done if the 350 | key cannot be found. 351 | */ 352 | /*--------------------------------------------------------------------------*/ 353 | void dictionary_unset(dictionary * d, char * key) 354 | { 355 | unsigned hash ; 356 | int i ; 357 | 358 | hash = dictionary_hash(key); 359 | for (i=0 ; isize ; i++) { 360 | if (d->key[i]==NULL) 361 | continue ; 362 | /* Compare hash */ 363 | if (hash==d->hash[i]) { 364 | /* Compare string, to avoid hash collisions */ 365 | if (!strcmp(key, d->key[i])) { 366 | /* Found key */ 367 | break ; 368 | } 369 | } 370 | } 371 | if (i>=d->size) 372 | /* Key not found */ 373 | return ; 374 | 375 | free(d->key[i]); 376 | d->key[i] = NULL ; 377 | if (d->val[i]!=NULL) { 378 | free(d->val[i]); 379 | d->val[i] = NULL ; 380 | } 381 | d->hash[i] = 0 ; 382 | d->n -- ; 383 | return ; 384 | } 385 | 386 | 387 | /*-------------------------------------------------------------------------*/ 388 | /** 389 | @brief Set a key in a dictionary, providing an int. 390 | @param d Dictionary to update. 391 | @param key Key to modify or add 392 | @param val Integer value to store (will be stored as a string). 393 | @return void 394 | 395 | This helper function calls dictionary_set() with the provided integer 396 | converted to a string using %d. 397 | */ 398 | /*--------------------------------------------------------------------------*/ 399 | 400 | 401 | void dictionary_setint(dictionary * d, char * key, int val) 402 | { 403 | char sval[MAXVALSZ]; 404 | sprintf(sval, "%d", val); 405 | dictionary_set(d, key, sval); 406 | } 407 | 408 | 409 | /*-------------------------------------------------------------------------*/ 410 | /** 411 | @brief Set a key in a dictionary, providing a double. 412 | @param d Dictionary to update. 413 | @param key Key to modify or add 414 | @param val Double value to store (will be stored as a string). 415 | @return void 416 | 417 | This helper function calls dictionary_set() with the provided double 418 | converted to a string using %g. 419 | */ 420 | /*--------------------------------------------------------------------------*/ 421 | 422 | 423 | void dictionary_setdouble(dictionary * d, char * key, double val) 424 | { 425 | char sval[MAXVALSZ]; 426 | sprintf(sval, "%g", val); 427 | dictionary_set(d, key, sval); 428 | } 429 | 430 | 431 | 432 | /*-------------------------------------------------------------------------*/ 433 | /** 434 | @brief Dump a dictionary to an opened file pointer. 435 | @param d Dictionary to dump 436 | @param f Opened file pointer. 437 | @return void 438 | 439 | Dumps a dictionary onto an opened file pointer. Key pairs are printed out 440 | as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as 441 | output file pointers. 442 | */ 443 | /*--------------------------------------------------------------------------*/ 444 | 445 | void dictionary_dump(dictionary * d, FILE * out) 446 | { 447 | int i ; 448 | 449 | if (d==NULL || out==NULL) return ; 450 | if (d->n<1) { 451 | fprintf(out, "empty dictionary\n"); 452 | return ; 453 | } 454 | for (i=0 ; isize ; i++) { 455 | if (d->key[i]) { 456 | fprintf(out, "%20s\t[%s]\n", 457 | d->key[i], 458 | d->val[i] ? d->val[i] : "UNDEF"); 459 | } 460 | } 461 | return ; 462 | } 463 | 464 | 465 | 466 | /* Example code */ 467 | #ifdef TESTDIC 468 | #define NVALS 20000 469 | int main(int argc, char *argv[]) 470 | { 471 | dictionary * d ; 472 | char * val ; 473 | int i ; 474 | char cval[90] ; 475 | 476 | /* allocate blackboard */ 477 | printf("allocating...\n"); 478 | d = dictionary_new(0); 479 | 480 | /* Set values in blackboard */ 481 | printf("setting %d values...\n", NVALS); 482 | for (i=0 ; in != 0) { 500 | printf("error deleting values\n"); 501 | } 502 | 503 | printf("deallocating...\n"); 504 | dictionary_del(d); 505 | return 0 ; 506 | } 507 | #endif 508 | /* vim: set ts=4 et sw=4 tw=75 */ 509 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/src/dictionary.h: -------------------------------------------------------------------------------- 1 | 2 | /*-------------------------------------------------------------------------*/ 3 | /** 4 | @file dictionary.h 5 | @author N. Devillard 6 | @date Aug 2000 7 | @version $Revision: 1.11 $ 8 | @brief Implements a dictionary for string variables. 9 | 10 | This module implements a simple dictionary object, i.e. a list 11 | of string/string associations. This object is useful to store e.g. 12 | informations retrieved from a configuration file (ini files). 13 | */ 14 | /*--------------------------------------------------------------------------*/ 15 | 16 | /* 17 | $Id: dictionary.h,v 1.11 2002/06/17 09:30:46 ndevilla Exp $ 18 | $Author: ndevilla $ 19 | $Date: 2002/06/17 09:30:46 $ 20 | $Revision: 1.11 $ 21 | */ 22 | 23 | #ifndef _DICTIONARY_H_ 24 | #define _DICTIONARY_H_ 25 | 26 | /*--------------------------------------------------------------------------- 27 | Includes 28 | ---------------------------------------------------------------------------*/ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | /*--------------------------------------------------------------------------- 36 | New types 37 | ---------------------------------------------------------------------------*/ 38 | 39 | 40 | /*-------------------------------------------------------------------------*/ 41 | /** 42 | @brief Dictionary object 43 | 44 | This object contains a list of string/string associations. Each 45 | association is identified by a unique string key. Looking up values 46 | in the dictionary is speeded up by the use of a (hopefully collision-free) 47 | hash function. 48 | */ 49 | /*-------------------------------------------------------------------------*/ 50 | typedef struct _dictionary_ { 51 | int n ; /** Number of entries in dictionary */ 52 | int size ; /** Storage size */ 53 | char ** val ; /** List of string values */ 54 | char ** key ; /** List of string keys */ 55 | unsigned * hash ; /** List of hash values for keys */ 56 | } dictionary ; 57 | 58 | 59 | /*--------------------------------------------------------------------------- 60 | Function prototypes 61 | ---------------------------------------------------------------------------*/ 62 | 63 | /*-------------------------------------------------------------------------*/ 64 | /** 65 | @brief Compute the hash key for a string. 66 | @param key Character string to use for key. 67 | @return 1 unsigned int on at least 32 bits. 68 | 69 | This hash function has been taken from an Article in Dr Dobbs Journal. 70 | This is normally a collision-free function, distributing keys evenly. 71 | The key is stored anyway in the struct so that collision can be avoided 72 | by comparing the key itself in last resort. 73 | */ 74 | /*--------------------------------------------------------------------------*/ 75 | unsigned dictionary_hash(char * key); 76 | 77 | /*-------------------------------------------------------------------------*/ 78 | /** 79 | @brief Create a new dictionary object. 80 | @param size Optional initial size of the dictionary. 81 | @return 1 newly allocated dictionary objet. 82 | 83 | This function allocates a new dictionary object of given size and returns 84 | it. If you do not know in advance (roughly) the number of entries in the 85 | dictionary, give size=0. 86 | */ 87 | /*--------------------------------------------------------------------------*/ 88 | dictionary * dictionary_new(int size); 89 | 90 | /*-------------------------------------------------------------------------*/ 91 | /** 92 | @brief Delete a dictionary object 93 | @param d dictionary object to deallocate. 94 | @return void 95 | 96 | Deallocate a dictionary object and all memory associated to it. 97 | */ 98 | /*--------------------------------------------------------------------------*/ 99 | void dictionary_del(dictionary * vd); 100 | 101 | /*-------------------------------------------------------------------------*/ 102 | /** 103 | @brief Get a value from a dictionary. 104 | @param d dictionary object to search. 105 | @param key Key to look for in the dictionary. 106 | @param def Default value to return if key not found. 107 | @return 1 pointer to internally allocated character string. 108 | 109 | This function locates a key in a dictionary and returns a pointer to its 110 | value, or the passed 'def' pointer if no such key can be found in 111 | dictionary. The returned character pointer points to data internal to the 112 | dictionary object, you should not try to free it or modify it. 113 | */ 114 | /*--------------------------------------------------------------------------*/ 115 | char * dictionary_get(dictionary * d, char * key, char * def); 116 | 117 | 118 | /*-------------------------------------------------------------------------*/ 119 | /** 120 | @brief Get a value from a dictionary, as a char. 121 | @param d dictionary object to search. 122 | @param key Key to look for in the dictionary. 123 | @param def Default value for the key if not found. 124 | @return char 125 | 126 | This function locates a key in a dictionary using dictionary_get, 127 | and returns the first char of the found string. 128 | */ 129 | /*--------------------------------------------------------------------------*/ 130 | char dictionary_getchar(dictionary * d, char * key, char def) ; 131 | 132 | /*-------------------------------------------------------------------------*/ 133 | /** 134 | @brief Get a value from a dictionary, as an int. 135 | @param d dictionary object to search. 136 | @param key Key to look for in the dictionary. 137 | @param def Default value for the key if not found. 138 | @return int 139 | 140 | This function locates a key in a dictionary using dictionary_get, 141 | and applies atoi on it to return an int. If the value cannot be found 142 | in the dictionary, the default is returned. 143 | */ 144 | /*--------------------------------------------------------------------------*/ 145 | int dictionary_getint(dictionary * d, char * key, int def); 146 | 147 | /*-------------------------------------------------------------------------*/ 148 | /** 149 | @brief Get a value from a dictionary, as a double. 150 | @param d dictionary object to search. 151 | @param key Key to look for in the dictionary. 152 | @param def Default value for the key if not found. 153 | @return double 154 | 155 | This function locates a key in a dictionary using dictionary_get, 156 | and applies atof on it to return a double. If the value cannot be found 157 | in the dictionary, the default is returned. 158 | */ 159 | /*--------------------------------------------------------------------------*/ 160 | double dictionary_getdouble(dictionary * d, char * key, double def); 161 | 162 | /*-------------------------------------------------------------------------*/ 163 | /** 164 | @brief Set a value in a dictionary. 165 | @param d dictionary object to modify. 166 | @param key Key to modify or add. 167 | @param val Value to add. 168 | @return void 169 | 170 | If the given key is found in the dictionary, the associated value is 171 | replaced by the provided one. If the key cannot be found in the 172 | dictionary, it is added to it. 173 | 174 | It is Ok to provide a NULL value for val, but NULL values for the dictionary 175 | or the key are considered as errors: the function will return immediately 176 | in such a case. 177 | 178 | Notice that if you dictionary_set a variable to NULL, a call to 179 | dictionary_get will return a NULL value: the variable will be found, and 180 | its value (NULL) is returned. In other words, setting the variable 181 | content to NULL is equivalent to deleting the variable from the 182 | dictionary. It is not possible (in this implementation) to have a key in 183 | the dictionary without value. 184 | */ 185 | /*--------------------------------------------------------------------------*/ 186 | void dictionary_set(dictionary * vd, char * key, char * val); 187 | 188 | /*-------------------------------------------------------------------------*/ 189 | /** 190 | @brief Delete a key in a dictionary 191 | @param d dictionary object to modify. 192 | @param key Key to remove. 193 | @return void 194 | 195 | This function deletes a key in a dictionary. Nothing is done if the 196 | key cannot be found. 197 | */ 198 | /*--------------------------------------------------------------------------*/ 199 | void dictionary_unset(dictionary * d, char * key); 200 | 201 | 202 | /*-------------------------------------------------------------------------*/ 203 | /** 204 | @brief Set a key in a dictionary, providing an int. 205 | @param d Dictionary to update. 206 | @param key Key to modify or add 207 | @param val Integer value to store (will be stored as a string). 208 | @return void 209 | 210 | This helper function calls dictionary_set() with the provided integer 211 | converted to a string using %d. 212 | */ 213 | /*--------------------------------------------------------------------------*/ 214 | void dictionary_setint(dictionary * d, char * key, int val); 215 | 216 | /*-------------------------------------------------------------------------*/ 217 | /** 218 | @brief Set a key in a dictionary, providing a double. 219 | @param d Dictionary to update. 220 | @param key Key to modify or add 221 | @param val Double value to store (will be stored as a string). 222 | @return void 223 | 224 | This helper function calls dictionary_set() with the provided double 225 | converted to a string using %g. 226 | */ 227 | /*--------------------------------------------------------------------------*/ 228 | void dictionary_setdouble(dictionary * d, char * key, double val); 229 | 230 | /*-------------------------------------------------------------------------*/ 231 | /** 232 | @brief Dump a dictionary to an opened file pointer. 233 | @param d Dictionary to dump 234 | @param f Opened file pointer. 235 | @return void 236 | 237 | Dumps a dictionary onto an opened file pointer. Key pairs are printed out 238 | as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as 239 | output file pointers. 240 | */ 241 | /*--------------------------------------------------------------------------*/ 242 | void dictionary_dump(dictionary * d, FILE * out); 243 | 244 | #endif 245 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/src/iniparser.c: -------------------------------------------------------------------------------- 1 | 2 | /*-------------------------------------------------------------------------*/ 3 | /** 4 | @file iniparser.c 5 | @author N. Devillard 6 | @date Mar 2000 7 | @version $Revision: 2.14 $ 8 | @brief Parser for ini files. 9 | */ 10 | /*--------------------------------------------------------------------------*/ 11 | 12 | /* 13 | $Id: iniparser.c,v 2.14 2002/12/12 10:49:01 ndevilla Exp $ 14 | $Author: ndevilla $ 15 | $Date: 2002/12/12 10:49:01 $ 16 | $Revision: 2.14 $ 17 | */ 18 | 19 | /*--------------------------------------------------------------------------- 20 | Includes 21 | ---------------------------------------------------------------------------*/ 22 | 23 | #include "iniparser.h" 24 | #include "strlib.h" 25 | 26 | #define ASCIILINESZ 1024 27 | #define INI_INVALID_KEY ((char*)-1) 28 | 29 | /*--------------------------------------------------------------------------- 30 | Private to this module 31 | ---------------------------------------------------------------------------*/ 32 | 33 | /* Private: add an entry to the dictionary */ 34 | static void iniparser_add_entry( 35 | dictionary * d, 36 | char * sec, 37 | char * key, 38 | char * val) 39 | { 40 | char longkey[2*ASCIILINESZ+1]; 41 | 42 | /* Make a key as section:keyword */ 43 | if (key!=NULL) { 44 | sprintf(longkey, "%s:%s", sec, key); 45 | } else { 46 | strcpy(longkey, sec); 47 | } 48 | 49 | /* Add (key,val) to dictionary */ 50 | dictionary_set(d, longkey, val); 51 | return ; 52 | } 53 | 54 | 55 | /*-------------------------------------------------------------------------*/ 56 | /** 57 | @brief Get number of sections in a dictionary 58 | @param d Dictionary to examine 59 | @return int Number of sections found in dictionary 60 | 61 | This function returns the number of sections found in a dictionary. 62 | The test to recognize sections is done on the string stored in the 63 | dictionary: a section name is given as "section" whereas a key is 64 | stored as "section:key", thus the test looks for entries that do not 65 | contain a colon. 66 | 67 | This clearly fails in the case a section name contains a colon, but 68 | this should simply be avoided. 69 | 70 | This function returns -1 in case of error. 71 | */ 72 | /*--------------------------------------------------------------------------*/ 73 | 74 | int iniparser_getnsec(dictionary * d) 75 | { 76 | int i ; 77 | int nsec ; 78 | 79 | if (d==NULL) return -1 ; 80 | nsec=0 ; 81 | for (i=0 ; isize ; i++) { 82 | if (d->key[i]==NULL) 83 | continue ; 84 | if (strchr(d->key[i], ':')==NULL) { 85 | nsec ++ ; 86 | } 87 | } 88 | return nsec ; 89 | } 90 | 91 | 92 | /*-------------------------------------------------------------------------*/ 93 | /** 94 | @brief Get name for section n in a dictionary. 95 | @param d Dictionary to examine 96 | @param n Section number (from 0 to nsec-1). 97 | @return Pointer to char string 98 | 99 | This function locates the n-th section in a dictionary and returns 100 | its name as a pointer to a string statically allocated inside the 101 | dictionary. Do not free or modify the returned string! 102 | 103 | This function returns NULL in case of error. 104 | */ 105 | /*--------------------------------------------------------------------------*/ 106 | 107 | char * iniparser_getsecname(dictionary * d, int n) 108 | { 109 | int i ; 110 | int foundsec ; 111 | 112 | if (d==NULL || n<0) return NULL ; 113 | foundsec=0 ; 114 | for (i=0 ; isize ; i++) { 115 | if (d->key[i]==NULL) 116 | continue ; 117 | if (strchr(d->key[i], ':')==NULL) { 118 | foundsec++ ; 119 | if (foundsec>n) 120 | break ; 121 | } 122 | } 123 | if (foundsec<=n) { 124 | return NULL ; 125 | } 126 | return d->key[i] ; 127 | } 128 | 129 | 130 | /*-------------------------------------------------------------------------*/ 131 | /** 132 | @brief Dump a dictionary to an opened file pointer. 133 | @param d Dictionary to dump. 134 | @param f Opened file pointer to dump to. 135 | @return void 136 | 137 | This function prints out the contents of a dictionary, one element by 138 | line, onto the provided file pointer. It is OK to specify @c stderr 139 | or @c stdout as output files. This function is meant for debugging 140 | purposes mostly. 141 | */ 142 | /*--------------------------------------------------------------------------*/ 143 | void iniparser_dump(dictionary * d, FILE * f) 144 | { 145 | int i ; 146 | 147 | if (d==NULL || f==NULL) return ; 148 | for (i=0 ; isize ; i++) { 149 | if (d->key[i]==NULL) 150 | continue ; 151 | if (d->val[i]!=NULL) { 152 | fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); 153 | } else { 154 | fprintf(f, "[%s]=UNDEF\n", d->key[i]); 155 | } 156 | } 157 | return ; 158 | } 159 | 160 | /*-------------------------------------------------------------------------*/ 161 | /** 162 | @brief Save a dictionary to a loadable ini file 163 | @param d Dictionary to dump 164 | @param f Opened file pointer to dump to 165 | @return void 166 | 167 | This function dumps a given dictionary into a loadable ini file. 168 | It is Ok to specify @c stderr or @c stdout as output files. 169 | */ 170 | /*--------------------------------------------------------------------------*/ 171 | 172 | void iniparser_dump_ini(dictionary * d, FILE * f) 173 | { 174 | int i, j ; 175 | char keym[ASCIILINESZ+1]; 176 | int nsec ; 177 | char * secname ; 178 | int seclen ; 179 | 180 | if (d==NULL || f==NULL) return ; 181 | 182 | nsec = iniparser_getnsec(d); 183 | if (nsec<1) { 184 | /* No section in file: dump all keys as they are */ 185 | for (i=0 ; isize ; i++) { 186 | if (d->key[i]==NULL) 187 | continue ; 188 | fprintf(f, "%s = %s\n", d->key[i], d->val[i]); 189 | } 190 | return ; 191 | } 192 | for (i=0 ; isize ; j++) { 198 | if (d->key[j]==NULL) 199 | continue ; 200 | if (!strncmp(d->key[j], keym, seclen+1)) { 201 | fprintf(f, 202 | "%-30s = %s\n", 203 | d->key[j]+seclen+1, 204 | d->val[j] ? d->val[j] : ""); 205 | } 206 | } 207 | } 208 | fprintf(f, "\n"); 209 | return ; 210 | } 211 | 212 | 213 | 214 | 215 | /*-------------------------------------------------------------------------*/ 216 | /** 217 | @brief Get the string associated to a key, return NULL if not found 218 | @param d Dictionary to search 219 | @param key Key string to look for 220 | @return pointer to statically allocated character string, or NULL. 221 | 222 | This function queries a dictionary for a key. A key as read from an 223 | ini file is given as "section:key". If the key cannot be found, 224 | NULL is returned. 225 | The returned char pointer is pointing to a string allocated in 226 | the dictionary, do not free or modify it. 227 | 228 | This function is only provided for backwards compatibility with 229 | previous versions of iniparser. It is recommended to use 230 | iniparser_getstring() instead. 231 | */ 232 | /*--------------------------------------------------------------------------*/ 233 | char * iniparser_getstr(dictionary * d, char * key) 234 | { 235 | return iniparser_getstring(d, key, NULL); 236 | } 237 | 238 | 239 | /*-------------------------------------------------------------------------*/ 240 | /** 241 | @brief Get the string associated to a key 242 | @param d Dictionary to search 243 | @param key Key string to look for 244 | @param def Default value to return if key not found. 245 | @return pointer to statically allocated character string 246 | 247 | This function queries a dictionary for a key. A key as read from an 248 | ini file is given as "section:key". If the key cannot be found, 249 | the pointer passed as 'def' is returned. 250 | The returned char pointer is pointing to a string allocated in 251 | the dictionary, do not free or modify it. 252 | */ 253 | /*--------------------------------------------------------------------------*/ 254 | char * iniparser_getstring(dictionary * d, char * key, char * def) 255 | { 256 | char * lc_key ; 257 | char * sval ; 258 | 259 | if (d==NULL || key==NULL) 260 | return def ; 261 | 262 | lc_key = strdup(strlwc(key)); 263 | sval = dictionary_get(d, lc_key, def); 264 | free(lc_key); 265 | return sval ; 266 | } 267 | 268 | 269 | 270 | /*-------------------------------------------------------------------------*/ 271 | /** 272 | @brief Get the string associated to a key, convert to an int 273 | @param d Dictionary to search 274 | @param key Key string to look for 275 | @param notfound Value to return in case of error 276 | @return integer 277 | 278 | This function queries a dictionary for a key. A key as read from an 279 | ini file is given as "section:key". If the key cannot be found, 280 | the notfound value is returned. 281 | */ 282 | /*--------------------------------------------------------------------------*/ 283 | int iniparser_getint(dictionary * d, char * key, int notfound) 284 | { 285 | char * str ; 286 | int len; 287 | int value; 288 | 289 | str = iniparser_getstring(d, key, INI_INVALID_KEY); 290 | if (str==INI_INVALID_KEY) return notfound ; 291 | 292 | /* Check if it is hexadecimal */ 293 | len = strlen(str); 294 | if (len > 2) 295 | { 296 | if ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) 297 | { 298 | sscanf(str,"%x",&value); 299 | return value; 300 | 301 | } 302 | } 303 | 304 | /* Check if specified in Kilobytes */ 305 | if ((str[len-1] == 'K') || (str[len-1] == 'k')) 306 | { 307 | value = atoi(str); 308 | return value*1024; 309 | } 310 | 311 | /* Check if specified in Megabytes */ 312 | if ((str[len-1] == 'M') || (str[len-1] == 'm')) 313 | { 314 | value = atoi(str); 315 | return value*1024*1024; 316 | } 317 | 318 | /* Normal integer */ 319 | return atoi(str); 320 | } 321 | 322 | /*-------------------------------------------------------------------------*/ 323 | /** 324 | @brief Get the string associated to a key, convert to an long 325 | @param d Dictionary to search 326 | @param key Key string to look for 327 | @param notfound Value to return in case of error 328 | @return long 329 | 330 | This function queries a dictionary for a key. A key as read from an 331 | ini file is given as "section:key". If the key cannot be found, 332 | the notfound value is returned. 333 | */ 334 | /*--------------------------------------------------------------------------*/ 335 | long iniparser_getlong(dictionary * d, char * key, long notfound) 336 | { 337 | char * str ; 338 | int len; 339 | long value; 340 | 341 | str = iniparser_getstring(d, key, INI_INVALID_KEY); 342 | if (str==INI_INVALID_KEY) return notfound ; 343 | 344 | /* Check if it is hexadecimal */ 345 | len = strlen(str); 346 | if (len > 2) 347 | { 348 | if ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) 349 | { 350 | sscanf(str,"%lx",&value); 351 | return value; 352 | } 353 | } 354 | 355 | /* Check if specified in Kilobytes */ 356 | if ((str[len-1] == 'K') || (str[len-1] == 'k')) 357 | { 358 | value = atol(str); 359 | return value*1024; 360 | } 361 | 362 | /* Check if specified in Megabytes */ 363 | if ((str[len-1] == 'M') || (str[len-1] == 'm')) 364 | { 365 | value = atol(str); 366 | return value*1024*1024; 367 | } 368 | 369 | /* Normal long integer */ 370 | return atol(str); 371 | } 372 | 373 | 374 | /*-------------------------------------------------------------------------*/ 375 | /** 376 | @brief Get the string associated to a key, convert to a double 377 | @param d Dictionary to search 378 | @param key Key string to look for 379 | @param notfound Value to return in case of error 380 | @return double 381 | 382 | This function queries a dictionary for a key. A key as read from an 383 | ini file is given as "section:key". If the key cannot be found, 384 | the notfound value is returned. 385 | */ 386 | /*--------------------------------------------------------------------------*/ 387 | double iniparser_getdouble(dictionary * d, char * key, double notfound) 388 | { 389 | char * str ; 390 | 391 | str = iniparser_getstring(d, key, INI_INVALID_KEY); 392 | if (str==INI_INVALID_KEY) return notfound ; 393 | return atof(str); 394 | } 395 | 396 | 397 | 398 | /*-------------------------------------------------------------------------*/ 399 | /** 400 | @brief Get the string associated to a key, convert to a boolean 401 | @param d Dictionary to search 402 | @param key Key string to look for 403 | @param notfound Value to return in case of error 404 | @return integer 405 | 406 | This function queries a dictionary for a key. A key as read from an 407 | ini file is given as "section:key". If the key cannot be found, 408 | the notfound value is returned. 409 | 410 | A true boolean is found if one of the following is matched: 411 | 412 | - A string starting with 'y' 413 | - A string starting with 'Y' 414 | - A string starting with 't' 415 | - A string starting with 'T' 416 | - A string starting with '1' 417 | 418 | A false boolean is found if one of the following is matched: 419 | 420 | - A string starting with 'n' 421 | - A string starting with 'N' 422 | - A string starting with 'f' 423 | - A string starting with 'F' 424 | - A string starting with '0' 425 | 426 | The notfound value returned if no boolean is identified, does not 427 | necessarily have to be 0 or 1. 428 | */ 429 | /*--------------------------------------------------------------------------*/ 430 | int iniparser_getboolean(dictionary * d, char * key, int notfound) 431 | { 432 | char * c ; 433 | int ret ; 434 | 435 | c = iniparser_getstring(d, key, INI_INVALID_KEY); 436 | if (c==INI_INVALID_KEY) return notfound ; 437 | if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { 438 | ret = 1 ; 439 | } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { 440 | ret = 0 ; 441 | } else { 442 | ret = notfound ; 443 | } 444 | return ret; 445 | } 446 | 447 | 448 | /*-------------------------------------------------------------------------*/ 449 | /** 450 | @brief Finds out if a given entry exists in a dictionary 451 | @param ini Dictionary to search 452 | @param entry Name of the entry to look for 453 | @return integer 1 if entry exists, 0 otherwise 454 | 455 | Finds out if a given entry exists in the dictionary. Since sections 456 | are stored as keys with NULL associated values, this is the only way 457 | of querying for the presence of sections in a dictionary. 458 | */ 459 | /*--------------------------------------------------------------------------*/ 460 | 461 | int iniparser_find_entry( 462 | dictionary * ini, 463 | char * entry 464 | ) 465 | { 466 | int found=0 ; 467 | if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { 468 | found = 1 ; 469 | } 470 | return found ; 471 | } 472 | 473 | 474 | 475 | /*-------------------------------------------------------------------------*/ 476 | /** 477 | @brief Set an entry in a dictionary. 478 | @param ini Dictionary to modify. 479 | @param entry Entry to modify (entry name) 480 | @param val New value to associate to the entry. 481 | @return int 0 if Ok, -1 otherwise. 482 | 483 | If the given entry can be found in the dictionary, it is modified to 484 | contain the provided value. If it cannot be found, -1 is returned. 485 | It is Ok to set val to NULL. 486 | */ 487 | /*--------------------------------------------------------------------------*/ 488 | 489 | int iniparser_setstr(dictionary * ini, char * entry, char * val) 490 | { 491 | dictionary_set(ini, strlwc(entry), val); 492 | return 0 ; 493 | } 494 | 495 | /*-------------------------------------------------------------------------*/ 496 | /** 497 | @brief Delete an entry in a dictionary 498 | @param ini Dictionary to modify 499 | @param entry Entry to delete (entry name) 500 | @return void 501 | 502 | If the given entry can be found, it is deleted from the dictionary. 503 | */ 504 | /*--------------------------------------------------------------------------*/ 505 | void iniparser_unset(dictionary * ini, char * entry) 506 | { 507 | dictionary_unset(ini, strlwc(entry)); 508 | } 509 | 510 | 511 | /*-------------------------------------------------------------------------*/ 512 | /** 513 | @brief Parse an ini file and return an allocated dictionary object 514 | @param ininame Name of the ini file to read. 515 | @return Pointer to newly allocated dictionary 516 | 517 | This is the parser for ini files. This function is called, providing 518 | the name of the file to be read. It returns a dictionary object that 519 | should not be accessed directly, but through accessor functions 520 | instead. 521 | 522 | The returned dictionary must be freed using iniparser_freedict(). 523 | */ 524 | /*--------------------------------------------------------------------------*/ 525 | 526 | dictionary * iniparser_load(char * ininame) 527 | { 528 | dictionary * d ; 529 | char lin[ASCIILINESZ+1]; 530 | char sec[ASCIILINESZ+1]; 531 | char key[ASCIILINESZ+1]; 532 | char val[ASCIILINESZ+1]; 533 | char * where ; 534 | FILE * ini ; 535 | int lineno ; 536 | 537 | if ((ini=fopen(ininame, "r"))==NULL) { 538 | return NULL ; 539 | } 540 | 541 | sec[0]=0; 542 | 543 | /* 544 | * Initialize a new dictionary entry 545 | */ 546 | d = dictionary_new(0); 547 | lineno = 0 ; 548 | while (fgets(lin, ASCIILINESZ, ini)!=NULL) { 549 | lineno++ ; 550 | where = strskp(lin); /* Skip leading spaces */ 551 | if (*where==';' || *where=='#' || *where==0) 552 | continue ; /* Comment lines */ 553 | else { 554 | if (sscanf(where, "[%[^]]", sec)==1) { 555 | /* Valid section name */ 556 | strcpy(sec, strlwc(sec)); 557 | iniparser_add_entry(d, sec, NULL, NULL); 558 | } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2 559 | || sscanf (where, "%[^=] = '%[^\']'", key, val) == 2 560 | || sscanf (where, "%[^=] = %[^;#]", key, val) == 2) { 561 | strcpy(key, strlwc(strcrop(key))); 562 | /* 563 | * sscanf cannot handle "" or '' as empty value, 564 | * this is done here 565 | */ 566 | if (!strcmp(val, "\"\"") || !strcmp(val, "''")) { 567 | val[0] = (char)0; 568 | } else { 569 | strcpy(val, strcrop(val)); 570 | } 571 | iniparser_add_entry(d, sec, key, val); 572 | } 573 | } 574 | } 575 | fclose(ini); 576 | return d ; 577 | } 578 | 579 | 580 | 581 | /*-------------------------------------------------------------------------*/ 582 | /** 583 | @brief Free all memory associated to an ini dictionary 584 | @param d Dictionary to free 585 | @return void 586 | 587 | Free all memory associated to an ini dictionary. 588 | It is mandatory to call this function before the dictionary object 589 | gets out of the current context. 590 | */ 591 | /*--------------------------------------------------------------------------*/ 592 | 593 | void iniparser_freedict(dictionary * d) 594 | { 595 | dictionary_del(d); 596 | } 597 | 598 | /* vim: set ts=4 et sw=4 tw=75 */ 599 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/src/iniparser.h: -------------------------------------------------------------------------------- 1 | 2 | /*-------------------------------------------------------------------------*/ 3 | /** 4 | @file iniparser.h 5 | @author N. Devillard 6 | @date Mar 2000 7 | @version $Revision: 1.19 $ 8 | @brief Parser for ini files. 9 | */ 10 | /*--------------------------------------------------------------------------*/ 11 | 12 | /* 13 | $Id: iniparser.h,v 1.19 2003/01/14 10:48:59 ndevilla Exp $ 14 | $Author: ndevilla $ 15 | $Date: 2003/01/14 10:48:59 $ 16 | $Revision: 1.19 $ 17 | */ 18 | 19 | #ifndef _INIPARSER_H_ 20 | #define _INIPARSER_H_ 21 | 22 | /*--------------------------------------------------------------------------- 23 | Includes 24 | ---------------------------------------------------------------------------*/ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "dictionary.h" 32 | 33 | /*-------------------------------------------------------------------------*/ 34 | /** 35 | @brief Get number of sections in a dictionary 36 | @param d Dictionary to examine 37 | @return int Number of sections found in dictionary 38 | 39 | This function returns the number of sections found in a dictionary. 40 | The test to recognize sections is done on the string stored in the 41 | dictionary: a section name is given as "section" whereas a key is 42 | stored as "section:key", thus the test looks for entries that do not 43 | contain a colon. 44 | 45 | This clearly fails in the case a section name contains a colon, but 46 | this should simply be avoided. 47 | 48 | This function returns -1 in case of error. 49 | */ 50 | /*--------------------------------------------------------------------------*/ 51 | 52 | int iniparser_getnsec(dictionary * d); 53 | 54 | 55 | /*-------------------------------------------------------------------------*/ 56 | /** 57 | @brief Get name for section n in a dictionary. 58 | @param d Dictionary to examine 59 | @param n Section number (from 0 to nsec-1). 60 | @return Pointer to char string 61 | 62 | This function locates the n-th section in a dictionary and returns 63 | its name as a pointer to a string statically allocated inside the 64 | dictionary. Do not free or modify the returned string! 65 | 66 | This function returns NULL in case of error. 67 | */ 68 | /*--------------------------------------------------------------------------*/ 69 | 70 | char * iniparser_getsecname(dictionary * d, int n); 71 | 72 | 73 | /*-------------------------------------------------------------------------*/ 74 | /** 75 | @brief Save a dictionary to a loadable ini file 76 | @param d Dictionary to dump 77 | @param f Opened file pointer to dump to 78 | @return void 79 | 80 | This function dumps a given dictionary into a loadable ini file. 81 | It is Ok to specify @c stderr or @c stdout as output files. 82 | */ 83 | /*--------------------------------------------------------------------------*/ 84 | 85 | void iniparser_dump_ini(dictionary * d, FILE * f); 86 | 87 | /*-------------------------------------------------------------------------*/ 88 | /** 89 | @brief Dump a dictionary to an opened file pointer. 90 | @param d Dictionary to dump. 91 | @param f Opened file pointer to dump to. 92 | @return void 93 | 94 | This function prints out the contents of a dictionary, one element by 95 | line, onto the provided file pointer. It is OK to specify @c stderr 96 | or @c stdout as output files. This function is meant for debugging 97 | purposes mostly. 98 | */ 99 | /*--------------------------------------------------------------------------*/ 100 | void iniparser_dump(dictionary * d, FILE * f); 101 | 102 | /*-------------------------------------------------------------------------*/ 103 | /** 104 | @brief Get the string associated to a key, return NULL if not found 105 | @param d Dictionary to search 106 | @param key Key string to look for 107 | @return pointer to statically allocated character string, or NULL. 108 | 109 | This function queries a dictionary for a key. A key as read from an 110 | ini file is given as "section:key". If the key cannot be found, 111 | NULL is returned. 112 | The returned char pointer is pointing to a string allocated in 113 | the dictionary, do not free or modify it. 114 | 115 | This function is only provided for backwards compatibility with 116 | previous versions of iniparser. It is recommended to use 117 | iniparser_getstring() instead. 118 | */ 119 | /*--------------------------------------------------------------------------*/ 120 | char * iniparser_getstr(dictionary * d, char * key); 121 | 122 | 123 | /*-------------------------------------------------------------------------*/ 124 | /** 125 | @brief Get the string associated to a key 126 | @param d Dictionary to search 127 | @param key Key string to look for 128 | @param def Default value to return if key not found. 129 | @return pointer to statically allocated character string 130 | 131 | This function queries a dictionary for a key. A key as read from an 132 | ini file is given as "section:key". If the key cannot be found, 133 | the pointer passed as 'def' is returned. 134 | The returned char pointer is pointing to a string allocated in 135 | the dictionary, do not free or modify it. 136 | */ 137 | /*--------------------------------------------------------------------------*/ 138 | char * iniparser_getstring(dictionary * d, char * key, char * def); 139 | 140 | /*-------------------------------------------------------------------------*/ 141 | /** 142 | @brief Get the string associated to a key, convert to an int 143 | @param d Dictionary to search 144 | @param key Key string to look for 145 | @param notfound Value to return in case of error 146 | @return integer 147 | 148 | This function queries a dictionary for a key. A key as read from an 149 | ini file is given as "section:key". If the key cannot be found, 150 | the notfound value is returned. 151 | */ 152 | /*--------------------------------------------------------------------------*/ 153 | int iniparser_getint(dictionary * d, char * key, int notfound); 154 | 155 | /*-------------------------------------------------------------------------*/ 156 | /** 157 | @brief Get the string associated to a key, convert to an long int 158 | @param d Dictionary to search 159 | @param key Key string to look for 160 | @param notfound Value to return in case of error 161 | @return long integer 162 | 163 | This function queries a dictionary for a key. A key as read from an 164 | ini file is given as "section:key". If the key cannot be found, 165 | the notfound value is returned. 166 | */ 167 | /*--------------------------------------------------------------------------*/ 168 | long iniparser_getlong(dictionary * d, char * key, long notfound); 169 | 170 | /*-------------------------------------------------------------------------*/ 171 | /** 172 | @brief Get the string associated to a key, convert to a double 173 | @param d Dictionary to search 174 | @param key Key string to look for 175 | @param notfound Value to return in case of error 176 | @return double 177 | 178 | This function queries a dictionary for a key. A key as read from an 179 | ini file is given as "section:key". If the key cannot be found, 180 | the notfound value is returned. 181 | */ 182 | /*--------------------------------------------------------------------------*/ 183 | double iniparser_getdouble(dictionary * d, char * key, double notfound); 184 | 185 | /*-------------------------------------------------------------------------*/ 186 | /** 187 | @brief Get the string associated to a key, convert to a boolean 188 | @param d Dictionary to search 189 | @param key Key string to look for 190 | @param notfound Value to return in case of error 191 | @return integer 192 | 193 | This function queries a dictionary for a key. A key as read from an 194 | ini file is given as "section:key". If the key cannot be found, 195 | the notfound value is returned. 196 | 197 | A true boolean is found if one of the following is matched: 198 | 199 | - A string starting with 'y' 200 | - A string starting with 'Y' 201 | - A string starting with 't' 202 | - A string starting with 'T' 203 | - A string starting with '1' 204 | 205 | A false boolean is found if one of the following is matched: 206 | 207 | - A string starting with 'n' 208 | - A string starting with 'N' 209 | - A string starting with 'f' 210 | - A string starting with 'F' 211 | - A string starting with '0' 212 | 213 | The notfound value returned if no boolean is identified, does not 214 | necessarily have to be 0 or 1. 215 | */ 216 | /*--------------------------------------------------------------------------*/ 217 | int iniparser_getboolean(dictionary * d, char * key, int notfound); 218 | 219 | 220 | /*-------------------------------------------------------------------------*/ 221 | /** 222 | @brief Set an entry in a dictionary. 223 | @param ini Dictionary to modify. 224 | @param entry Entry to modify (entry name) 225 | @param val New value to associate to the entry. 226 | @return int 0 if Ok, -1 otherwise. 227 | 228 | If the given entry can be found in the dictionary, it is modified to 229 | contain the provided value. If it cannot be found, -1 is returned. 230 | It is Ok to set val to NULL. 231 | */ 232 | /*--------------------------------------------------------------------------*/ 233 | 234 | int iniparser_setstr(dictionary * ini, char * entry, char * val); 235 | 236 | /*-------------------------------------------------------------------------*/ 237 | /** 238 | @brief Delete an entry in a dictionary 239 | @param ini Dictionary to modify 240 | @param entry Entry to delete (entry name) 241 | @return void 242 | 243 | If the given entry can be found, it is deleted from the dictionary. 244 | */ 245 | /*--------------------------------------------------------------------------*/ 246 | void iniparser_unset(dictionary * ini, char * entry); 247 | 248 | /*-------------------------------------------------------------------------*/ 249 | /** 250 | @brief Finds out if a given entry exists in a dictionary 251 | @param ini Dictionary to search 252 | @param entry Name of the entry to look for 253 | @return integer 1 if entry exists, 0 otherwise 254 | 255 | Finds out if a given entry exists in the dictionary. Since sections 256 | are stored as keys with NULL associated values, this is the only way 257 | of querying for the presence of sections in a dictionary. 258 | */ 259 | /*--------------------------------------------------------------------------*/ 260 | int iniparser_find_entry(dictionary * ini, char * entry) ; 261 | 262 | /*-------------------------------------------------------------------------*/ 263 | /** 264 | @brief Parse an ini file and return an allocated dictionary object 265 | @param ininame Name of the ini file to read. 266 | @return Pointer to newly allocated dictionary 267 | 268 | This is the parser for ini files. This function is called, providing 269 | the name of the file to be read. It returns a dictionary object that 270 | should not be accessed directly, but through accessor functions 271 | instead. 272 | 273 | The returned dictionary must be freed using iniparser_freedict(). 274 | */ 275 | /*--------------------------------------------------------------------------*/ 276 | dictionary * iniparser_load(char * ininame); 277 | 278 | /*-------------------------------------------------------------------------*/ 279 | /** 280 | @brief Free all memory associated to an ini dictionary 281 | @param d Dictionary to free 282 | @return void 283 | 284 | Free all memory associated to an ini dictionary. 285 | It is mandatory to call this function before the dictionary object 286 | gets out of the current context. 287 | */ 288 | /*--------------------------------------------------------------------------*/ 289 | void iniparser_freedict(dictionary * d); 290 | 291 | #endif 292 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/src/strlib.c: -------------------------------------------------------------------------------- 1 | 2 | /*-------------------------------------------------------------------------*/ 3 | /** 4 | @file strlib.c 5 | @author N. Devillard 6 | @date Jan 2001 7 | @version $Revision: 1.8 $ 8 | @brief Various string handling routines to complement the C lib. 9 | 10 | This modules adds a few complementary string routines usually missing 11 | in the standard C library. 12 | */ 13 | /*--------------------------------------------------------------------------*/ 14 | 15 | /* 16 | $Id: strlib.c,v 1.8 2002/12/12 10:29:16 ndevilla Exp $ 17 | $Author: ndevilla $ 18 | $Date: 2002/12/12 10:29:16 $ 19 | $Revision: 1.8 $ 20 | */ 21 | 22 | /*--------------------------------------------------------------------------- 23 | Includes 24 | ---------------------------------------------------------------------------*/ 25 | 26 | #include 27 | #include 28 | 29 | #include "strlib.h" 30 | 31 | /*--------------------------------------------------------------------------- 32 | Defines 33 | ---------------------------------------------------------------------------*/ 34 | #define ASCIILINESZ 1024 35 | 36 | /*--------------------------------------------------------------------------- 37 | Function codes 38 | ---------------------------------------------------------------------------*/ 39 | 40 | 41 | /*-------------------------------------------------------------------------*/ 42 | /** 43 | @brief Convert a string to lowercase. 44 | @param s String to convert. 45 | @return ptr to statically allocated string. 46 | 47 | This function returns a pointer to a statically allocated string 48 | containing a lowercased version of the input string. Do not free 49 | or modify the returned string! Since the returned string is statically 50 | allocated, it will be modified at each function call (not re-entrant). 51 | */ 52 | /*--------------------------------------------------------------------------*/ 53 | 54 | char * strlwc(char * s) 55 | { 56 | static char l[ASCIILINESZ+1]; 57 | int i ; 58 | 59 | if (s==NULL) return NULL ; 60 | memset(l, 0, ASCIILINESZ+1); 61 | i=0 ; 62 | while (s[i] && i l) { 149 | if (!isspace((int)*(last-1))) 150 | break ; 151 | last -- ; 152 | } 153 | *last = (char)0; 154 | return l ; 155 | } 156 | 157 | 158 | 159 | /*-------------------------------------------------------------------------*/ 160 | /** 161 | @brief Remove blanks at the beginning and the end of a string. 162 | @param s String to parse. 163 | @return ptr to statically allocated string. 164 | 165 | This function returns a pointer to a statically allocated string, 166 | which is identical to the input string, except that all blank 167 | characters at the end and the beg. of the string have been removed. 168 | Do not free or modify the returned string! Since the returned string 169 | is statically allocated, it will be modified at each function call 170 | (not re-entrant). 171 | */ 172 | /*--------------------------------------------------------------------------*/ 173 | char * strstrip(char * s) 174 | { 175 | static char l[ASCIILINESZ+1]; 176 | char * last ; 177 | 178 | if (s==NULL) return NULL ; 179 | 180 | while (isspace((int)*s) && *s) s++; 181 | 182 | memset(l, 0, ASCIILINESZ+1); 183 | strcpy(l, s); 184 | last = l + strlen(l); 185 | while (last > l) { 186 | if (!isspace((int)*(last-1))) 187 | break ; 188 | last -- ; 189 | } 190 | *last = (char)0; 191 | 192 | return (char*)l ; 193 | } 194 | 195 | /* Test code */ 196 | #ifdef TEST 197 | int main(int argc, char * argv[]) 198 | { 199 | char * str ; 200 | 201 | str = "\t\tI'm a lumberkack and I'm OK " ; 202 | printf("lowercase: [%s]\n", strlwc(str)); 203 | printf("uppercase: [%s]\n", strupc(str)); 204 | printf("skipped : [%s]\n", strskp(str)); 205 | printf("cropped : [%s]\n", strcrop(str)); 206 | printf("stripped : [%s]\n", strstrip(str)); 207 | 208 | return 0 ; 209 | } 210 | #endif 211 | /* vim: set ts=4 et sw=4 tw=75 */ 212 | -------------------------------------------------------------------------------- /genimage/iniparser-2.14/src/strlib.h: -------------------------------------------------------------------------------- 1 | 2 | /*-------------------------------------------------------------------------*/ 3 | /** 4 | @file strlib.h 5 | @author N. Devillard 6 | @date Jan 2001 7 | @version $Revision: 1.3 $ 8 | @brief Various string handling routines to complement the C lib. 9 | 10 | This modules adds a few complementary string routines usually missing 11 | in the standard C library. 12 | */ 13 | /*--------------------------------------------------------------------------*/ 14 | 15 | /* 16 | $Id: strlib.h,v 1.3 2001/10/19 08:31:41 ndevilla Exp $ 17 | $Author: ndevilla $ 18 | $Date: 2001/10/19 08:31:41 $ 19 | $Revision: 1.3 $ 20 | */ 21 | 22 | #ifndef _STRLIB_H_ 23 | #define _STRLIB_H_ 24 | 25 | /*--------------------------------------------------------------------------- 26 | Includes 27 | ---------------------------------------------------------------------------*/ 28 | 29 | #include 30 | #include 31 | 32 | /*--------------------------------------------------------------------------- 33 | Function codes 34 | ---------------------------------------------------------------------------*/ 35 | 36 | /*-------------------------------------------------------------------------*/ 37 | /** 38 | @brief Convert a string to lowercase. 39 | @param s String to convert. 40 | @return ptr to statically allocated string. 41 | 42 | This function returns a pointer to a statically allocated string 43 | containing a lowercased version of the input string. Do not free 44 | or modify the returned string! Since the returned string is statically 45 | allocated, it will be modified at each function call (not re-entrant). 46 | */ 47 | /*--------------------------------------------------------------------------*/ 48 | char * strlwc(char * s); 49 | 50 | /*-------------------------------------------------------------------------*/ 51 | /** 52 | @brief Convert a string to uppercase. 53 | @param s String to convert. 54 | @return ptr to statically allocated string. 55 | 56 | This function returns a pointer to a statically allocated string 57 | containing an uppercased version of the input string. Do not free 58 | or modify the returned string! Since the returned string is statically 59 | allocated, it will be modified at each function call (not re-entrant). 60 | */ 61 | /*--------------------------------------------------------------------------*/ 62 | char * strupc(char * s); 63 | 64 | /*-------------------------------------------------------------------------*/ 65 | /** 66 | @brief Skip blanks until the first non-blank character. 67 | @param s String to parse. 68 | @return Pointer to char inside given string. 69 | 70 | This function returns a pointer to the first non-blank character in the 71 | given string. 72 | */ 73 | /*--------------------------------------------------------------------------*/ 74 | char * strskp(char * s); 75 | 76 | /*-------------------------------------------------------------------------*/ 77 | /** 78 | @brief Remove blanks at the end of a string. 79 | @param s String to parse. 80 | @return ptr to statically allocated string. 81 | 82 | This function returns a pointer to a statically allocated string, 83 | which is identical to the input string, except that all blank 84 | characters at the end of the string have been removed. 85 | Do not free or modify the returned string! Since the returned string 86 | is statically allocated, it will be modified at each function call 87 | (not re-entrant). 88 | */ 89 | /*--------------------------------------------------------------------------*/ 90 | char * strcrop(char * s); 91 | 92 | /*-------------------------------------------------------------------------*/ 93 | /** 94 | @brief Remove blanks at the beginning and the end of a string. 95 | @param s String to parse. 96 | @return ptr to statically allocated string. 97 | 98 | This function returns a pointer to a statically allocated string, 99 | which is identical to the input string, except that all blank 100 | characters at the end and the beg. of the string have been removed. 101 | Do not free or modify the returned string! Since the returned string 102 | is statically allocated, it will be modified at each function call 103 | (not re-entrant). 104 | */ 105 | /*--------------------------------------------------------------------------*/ 106 | char * strstrip(char * s) ; 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /genimage/renew-ima.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | PROG=${0##*/} 4 | 5 | usage() 6 | { 7 | cat < 23 | EOF 24 | [ "$1" = '-n' ] || exit ${1:-2} 25 | } 26 | 27 | fatal_msg() 28 | { 29 | echo "FATAL: $@" 1>&2 30 | exit 1 31 | } 32 | 33 | fatal_usage_msg() 34 | { 35 | usage -n 36 | fatal_msg "$@" 37 | } 38 | 39 | TEMP=`getopt -o p:d:o:m:h --long platofrm:,dump:,output:,mac:,help -n "$PROG" -- "$@" || usage 1>&2` 40 | 41 | eval set -- "$TEMP" 42 | 43 | opt_offset=$((0x30000)) 44 | opt_platform= 45 | opt_dump= 46 | opt_output= 47 | opt_mac= 48 | while :; do 49 | case "$1" in 50 | -p|--platform) shift 51 | opt_platform="$1" 52 | ;; 53 | -d|--dump) shift 54 | opt_dump="$1" 55 | ;; 56 | -o|--output) shift 57 | opt_output="$1" 58 | ;; 59 | -m|--mac) shift 60 | opt_mac="$(echo $1 | tr '[[:lower:]]' '[[:upper:]]')" 61 | ;; 62 | -h|--help) 63 | usage 0 64 | ;; 65 | --) shift 66 | break 67 | ;; 68 | *) 69 | usage 1 70 | ;; 71 | esac 72 | shift 73 | done 74 | 75 | [ -n "$opt_platform" ] || fatal_usage_msg "Platform not specified" 76 | 77 | [ -n "$opt_mac" ] || fatal_usage_msg "IPMI MAC not specified" 78 | 79 | echo -n "$opt_mac" | egrep -q '^[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}$' || 80 | fatal_msg "MAC ($opt_mac) is not in right format (aa:bb:cc:dd:ee:ff)" 81 | 82 | [ -e "stock/$opt_platform.ima" ] || 83 | fatal_msg "Platform $opt_platform is not supported. Available platforms:\n$(ls -1 stock/*.ima | sed "s,\.ima$,,; s,^stock/,\t,")" 84 | 85 | [ -n "$opt_output" ] || opt_output="$opt_platform-$(echo -n "$opt_mac" | tr '[[:upper:]]' '[[:lower:]]' | sed 's,:,,g').bin" 86 | 87 | [ -z "$opt_dump" ] || ./dumpimage -s -i "$opt_dump" -f "$(printf "%#x" $(($(stat -c %s stock/$opt_platform.ima) - 0x10000)))" 88 | 89 | case "$(($(stat -c %s stock/$opt_platform.ima)/0x100000))" in 90 | 32) # ASMB6 91 | flash_size=32M 92 | cmdline=`cat < 0; i--) printf "%c", 0 }' > $opt_output.cmdline 133 | 134 | # Calculate CRC32 for NVRAM and append it to the output 135 | cksfv -c $opt_output.cmdline | awk -vok=0 ' 136 | $1 != ";" { for (i=7; i>0; i-=2) printf "%c", int("0x" substr($2, i, 2)); ok = 1 } 137 | END { if (!ok) exit(1) }' >> $opt_output 138 | 139 | # Output NVRAM 140 | cat $opt_output.cmdline >> $opt_output 141 | 142 | # Append 0xFFFF_FFFF 143 | awk 'END {printf "%c%c%c%c", 255, 255, 255, 255}' < /dev/null >> $opt_output 144 | 145 | rm -f $opt_output.cmdline 146 | 147 | # Append rest of firmware image 148 | dd if=stock/$opt_platform.ima of=$opt_output bs=$((0x40000)) skip=1 seek=1 149 | 150 | # Pad with zeroes to the flash size 151 | dd if=$opt_output of=$opt_output bs=$flash_size conv=notrunc,sync count=1 152 | --------------------------------------------------------------------------------