Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / contrib / rom-o-matic / utils.php
1 <?php // -*- Mode: PHP; -*-
2
3 /**
4  * Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
5  * Copyright (C) 2009 Entity Cyber, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 // Include table of user-configurable iPXE options
23 require_once "flag-table.php";
24
25 // Include user-shadowable globals
26 require_once "globals.php";
27
28 // Allow user to shadow globals
29 if ( is_file ( 'local-config.php' ) ) {
30     include_once "local-config.php";
31 }
32
33 ////
34 // General utility functions
35 ////
36
37 /**
38  * Remove undesirable characters from a given string
39  *
40  * Certain characters have the potential to be used for
41  * malicious purposes by web-based attackers.  This routine
42  * filters out such characters.
43  *
44  * @param string $s supplied string
45  *
46  * @return string returned string with unwanted characters
47  *                removed
48  */
49 function cleanstring ( $s )
50 {
51     $len = strlen ( $s );
52     if ( $len > 80 ) {
53         $s = substr ( $s, 0, 80 );
54     }
55
56     $s      = trim ( $s );
57     $pos    = 0;
58     $result = "";
59
60     while ( $pos < $len ) {
61         $ltr = ord ( ucfirst ( $s[$pos] ) );
62         if ( ( $ltr >= ord ( "A" ) ) && ( $ltr <= ord ( "Z" ) ) ||
63              ( $ltr >= ord ( "0" ) ) && ( $ltr <= ord ( "9" ) ) ||
64              ( $ltr == ord ( "." ) ) && ( strlen ( $result ) > 0 ) ||
65              ( $ltr == ord ( "_" ) ) ||
66              ( $ltr == ord ( "+" ) ) ||
67              ( $ltr == ord ( ":" ) ) ||
68              ( $ltr == ord ( "/" ) ) ||
69              ( $ltr == ord ( "-" ) ) ) {
70             $result .= $s[$pos];
71         }
72         $pos++;
73     }
74     return $result;
75 }
76
77 /**
78  * Return URL of the currently running script, minus the filename
79  *
80  * @return string the URL of the currently running script, minus the filename
81  */
82 function curDirURL ()
83 {
84         $dir = dirname ( $_SERVER['PHP_SELF'] );
85
86         if ( $dir == "." || $dir == "/" ) {
87                 $dir = "";
88         }
89
90         $isHTTPS = ( isset ( $_SERVER["HTTPS"] ) && $_SERVER["HTTPS"] == "on" );
91         $port = ( isset($_SERVER["SERVER_PORT"] ) &&
92                           ( ( !$isHTTPS && $_SERVER["SERVER_PORT"] != "80" ) ||
93                                 ( $isHTTPS  && $_SERVER["SERVER_PORT"] != "443" ) ) );
94
95         $port = ( $port ) ? ':' . $_SERVER["SERVER_PORT"] : '';
96
97         $dest = ( $isHTTPS ? 'https://' : 'http://' ) .
98                 $_SERVER["SERVER_NAME"] . $dir . "/";
99
100         return $dest;
101 }
102
103 /**
104  * Extract NIC families and associated ROM PCI IDs from the src/bin/NIC file.
105  *
106  * $src_dir must contain the path of the iPXE src directory for this build
107  *
108  * @return array[0] array $new_nics
109  * @return array[1] array $roms
110  */
111 function parse_nic_file ()
112 {
113     global $src_dir;
114
115     $fd = fopen ( "$src_dir/bin/NIC", "r" );
116     if ( ! $fd ) {
117         die ( "Missing src/bin/NIC file.  'make bin/NIC'" );
118     }
119
120     $nics = array ();
121     $roms = array ();
122     $nic = "";
123
124     while ( !feof ( $fd ) ) {
125
126         $line = trim ( fgets ( $fd, 200 ) );
127
128         $first_eight_chars = substr ( $line, 0, 8 );
129         settype ( $first_eight_chars, "string" );
130
131         if ( strpos ( $first_eight_chars, "family" ) === 0 ) {
132
133             // get pathname of NIC driver
134             #list ( $dummy, $nic ) = split( "[ \t]+", $line );
135             list ( $dummy, $nic ) = explode("\t", $line);
136             settype ( $nic, "string" );
137
138             // extract filename name of driver from pathname
139             $nic = substr ( $nic, strrpos ( $nic, "/" ) + 1,
140                            strlen ( $nic ) - strrpos ( $nic, "/" ) + 1 );
141
142             $nics[$nic] = $nic;
143
144             // For each ISA NIC, there can only be one ROM variant
145             $roms[$nic] = $nic;
146         }
147
148         // If the first 8 digits of the line are hex digits
149         // add this rom to the current nic family.
150
151         if (    ( strlen ( $first_eight_chars ) == 8 )
152              && ( ctype_xdigit ( $first_eight_chars ) )
153              && ( $nic != "" ) ) {
154
155             $roms[$first_eight_chars] = $nic;
156         }
157     }
158     fclose ( $fd );
159
160     // put most NICs in nice alpha order for menu
161     ksort ( $nics );
162
163     // add special cases to the top
164
165         $new_nics = array ( "all-drivers" => "ipxe",
166                                                 "undionly" => "undionly",
167                                                 "undi" => "undi",
168     );
169
170         foreach ( $nics as $key => $value ) {
171                 // skip the undi driver
172                 if ( $key != "undi" ) {
173                         $new_nics[$key] = $value;
174                 }
175         }
176
177         return array ( $new_nics, $roms );
178 }
179
180 ////
181 // HTML form utility functions
182 ////
183
184 /**
185  * Return html code to create hidden form input fields
186  *
187  * @param string $flag  name of form variable to set
188  * @param string $value value to give form variable
189  *
190  * @return string html code for given hidden form input field
191  */
192 function hidden ( $flag, $value )
193 {
194     $value = htmlentities ( $value );
195     return "<input type=\"hidden\" value=\"$value\" name=\"$flag\"></input>";
196 }
197
198 /**
199  * Return html code to create checkbox form input fields
200  *
201  * @param string $flag  name of form variable to set
202  * @param string $value "on" means box should be checked
203  *
204  * @return string html code for given hidden form input field
205  */
206 function checkbox ( $flag, $value )
207 {
208     return "<input type=\"checkbox\" value=\"on\" name=\"$flag\"" .
209         ($value == "on" ? " checked>" : ">" );
210 }
211
212 /**
213  * Return html code to create text form input fields
214  *
215  * @param string $flag  name of form variable to set
216  * @param string $value initial contents of field
217  * @param string $size  size in characters of text box
218  *
219  * @return string html code for given text input field
220  */
221 function textbox ( $flag, $value, $size )
222 {
223     $value = htmlentities ( $value );
224     return "<input type=\"text\" size=\"$size\" value=\"$value\" name=\"$flag\">";
225 }
226
227 /**
228  * Return html code to create textarea form fields
229  *
230  * @param string $flag  name of form variable to set
231  * @param string $value initial contents of textarea
232  * @param string $rows  height of text area in rows
233  * @param string $cols  width of text area in columns
234  *
235  * @return string html code for given textarea input field
236  */
237 function textarea ( $flag, $value, $rows, $cols )
238 {
239     $value = htmlentities ( $value );
240     return "<textarea name=\"$flag\" rows=\"$rows\" cols=\"$cols\">"
241             . $value . "</textarea>";
242 }
243
244 /**
245  * Return html code to create select (menu) form fields
246  *
247  * Use array of strings as menu choices
248  *
249  * @param string $flag    name of form variable to set
250  * @param array  $options array of strings representing choices
251  * @param string $value   value of choice to select in menu
252  *
253  * @return string html code for given select (menu) input field
254  */
255 function menubox ( $name, $options, $value )
256 {
257     $s="<select name=\"$name\">";
258
259         foreach ( $options as $ignore => $option ) {
260         if ( !$value ) $value = $option;
261         $s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
262             htmlentities ( $option ) . "</option>";
263     }
264     return $s . "</select>";
265 }
266
267 /**
268  * Return html code to create select (menu) form fields
269  *
270  * Use indices of array of strings as menu choices rather than
271  * the values pointed to by the indicies.
272  *
273  * @param string $flag    name of form variable to set
274  * @param array  $options array of strings representing choices
275  * @param string $value   value of choice to select in menu
276  *
277  * @return string html code for given select (menu) input field
278  */
279 function keys_menubox ( $name, $options, $value )
280 {
281     $s="<select name=\"$name\">";
282
283     foreach ( $options as $option => $ignore ) {
284         if ( !$value ) $value = $option;
285         $s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
286             htmlentities ( $option ) . "</option>";
287     }
288     return $s . "</select>";
289 }
290
291 ////
292 // Flag (compile option) handling functions
293 ////
294
295 /**
296  * Return default compile options (flags)
297  *
298  * Initial compile options are in a global called $flag_table.
299  * Create and return an array containing the ones we want.
300  *
301  * @return array default compile options (flags)
302  */
303 function default_flags ()
304 {
305     global $flag_table;
306
307     $flags = array ();
308
309     foreach ( $flag_table as $key => $props ) {
310
311         $flag  = $props["flag"];
312         $type  = $props["type"];
313
314         // Fields like headers have no "value" property
315         if ( isset ( $props["value"] ) ) {
316             $flags[$flag] = $props["value"];
317         }
318     }
319     return $flags;
320 }
321
322 /**
323  * Return combination of default and user compile options (flags)
324  *
325  * Initial compile options are in a global called $flag_table.
326  * Compile options may have been changed via form input. We return
327  * an array with either the default value of each option or a user
328  * supplied value from form input.
329  *
330  * @return array combined default and user supplied compile options (flags)
331  */
332 function get_flags ()
333 {
334     global $flag_table;
335
336     $flags = default_flags ();
337
338     if ( ! isset ( $_POST["use_flags"] ) )
339         return $flags;
340
341     foreach ( $flag_table as $key => $props ) {
342
343         $flag = $props["flag"];
344         $type = $props["type"];
345
346         if ( isset ( $_POST["$flag"] ) ) {
347             $flags[$flag] = $_POST["$flag"];
348             if ( $type == "integer-hex" ) {
349                 if ( strtolower ( substr ( $flags[$flag], 0, 2 ) ) != "0x" ) {
350                     $flags[$flag] = "0x" . $flags[$flag];
351                 }
352             }
353         } else if ( $type == "on/off" ) {
354                         // Unchecked checkboxes don't pass any POST value
355                         // so we must check for them specially.  At this
356                         // point we know that there is no $_POST value set
357                         // for this option.  If it is a checkbox, this means
358                         // it is unchecked, so record that in $flags so we
359                         // can later generate an #undef for this option.
360             $flags[$flag] = "off";
361         }
362     }
363     return $flags;
364 }
365
366 /**
367  * Output given value in appropriate format for iPXE config file
368  *
369  * iPXE config/*.h files use C pre-processor syntax.  Output the given
370  * compile option in a format appropriate to its type
371  *
372  * @param string $key   index into $flag_table for given compile option
373  * @param string $value value we wish to set compile option to
374  *
375  * @return string code to set compile option to given value
376  */
377 function pprint_flag ( $key, $value )
378 {
379     global $flag_table;
380
381     // Determine type of given compile option (flag)
382     $type = $flag_table[$key]["type"];
383     $s = "";
384
385     if ( $type == "on/off" && $value == "on" ) {
386         $s = "#define $key";
387     } else if ( $type == "on/off" && $value != "on" ) {
388         $s = "#undef $key";
389     } else if ( $type == "string" ) {
390         $s = ( "#define $key \"" . cleanstring ( $value ) . "\"" );
391     } else if ($type == "qstring" ) {
392         $s = ( "#define $key \\\"" . cleanstring ( $value ) . "\\\"" );
393     } else {
394         $s = "#define $key " . cleanstring ( $value );
395     }
396
397     return $s;
398 }
399
400 /**
401  * Output html code to display all compile options as a table
402  *
403  * @param array $flags array of compile options
404  *
405  * @return void
406  */
407 function echo_flags ( $flags )
408 {
409     global $flag_table;
410
411     echo "<table>\n";
412
413         foreach ( $flag_table as $key => $props ) {
414
415         // Hide parameters from users that should not be changed.
416         $hide_from_user = isset ( $props["hide_from_user"] ) ? $props["hide_from_user"] : "no";
417
418         $flag = $props["flag"];
419         $type = $props["type"];
420
421         $value = isset ( $flags[$flag] ) ? $flags[$flag] : '';
422
423         if ( $hide_from_user == "yes" ) {
424
425             // Hidden flags cannot not be set by the user.  We use hidden form
426             // fields to keep them at their default values.
427             if ( $type != "header" ) {
428                 echo hidden ( $flag, $value );
429             }
430
431         } else {
432
433             // Flag (iPXE compile option) should be displayed to user
434
435             if ( $type == "header" ) {
436
437                 $label = $props["label"];
438                 echo "<td colspan=2><hr><h3>$label</h3><hr></td>";
439
440             } else if ($type == "on/off" ) {
441
442                 echo "<td>", checkbox ( $flag, $value ), "</td><td><strong>$flag</strong></td>";
443
444             } else {   // don't display checkbox for non-on/off flags
445
446                 echo "<td>&nbsp;</td><td><strong>$flag: </strong>";
447
448                 if ($type == "choice" ) {
449                     $options = $props["options"];
450                     echo menubox($flag, $options, $value);
451
452                 } else {
453
454                     echo textbox($flag, $value, ($type == "integer" ||
455                                                  $type == "integer-hex"
456                                                      ? 7 : 25));
457                 }
458                 echo "</td>";
459             }
460             echo "</tr>\n";
461
462             if ( $type != "header" ) {
463                                 echo "<tr><td>&nbsp;</td>";
464                                 echo "<td>\n";
465                                 if ( is_file ( "doc/$flag.html" ) ) {
466                                         include_once "doc/$flag.html";
467                                 }
468                                 echo "\n</td></tr>\n";
469             }
470         }
471     }
472     echo "</table>";
473 }
474
475 /**
476  * Return an array of configuration sections used in all compile options
477  *
478  * $flag_table, the global list of compile options contains a 'cfgsec'
479  * property for each flag we are interested in.  We return a list of
480  * all the unique cfgsec options we find in $flag_table.
481  *
482  * @return array an array of strings representing all unique cfgsec values
483  *               found in $flag_table
484  */
485 function get_flag_cfgsecs ()
486 {
487     global $flag_table;
488     $cfgsecs = array ();
489
490     foreach ( $flag_table as $key => $props ) {
491         if ( isset ( $props['cfgsec'] ) ) {
492             $cfgsec = $props["cfgsec"];
493             $cfgsecs[$cfgsec] = $cfgsec;
494         }
495     }
496     return $cfgsecs;
497 }
498
499 ////
500 // File and directory handling functions
501 ////
502
503 /**
504  * Create a copy of a given source directory to a given destination
505  *
506  * Since we are going to modify the source directory, we create a copy
507  * of the directory with a unique name in the given destination directory.
508  * We supply a prefix for the tempnam call to prepend to the random filename
509  * it generates.
510  *
511  * @param string $src    source directory
512  * @param string $dst    destination directory
513  * @param string $prefix string to append to directory created
514  *
515  * @return string absolute path to destination directory
516  */
517 function mktempcopy ( $src, $dst, $prefix )
518 {
519     if ( $src[0] != "/" ) {
520         $src = dirname ( $_SERVER['SCRIPT_FILENAME'] ) . "/" . $src;
521     }
522
523     // Create a file in the given destination directory with a unique name
524     $dir = tempnam ( $dst, $prefix );
525
526     // Delete the file just created, since it would interfere with the copy we
527     // are about to do.  We only care that the dir name we copy to is unique.
528     unlink ( $dir );
529
530     exec ( "/bin/cp -a '$src' '$dir' 2>&1", $cpytxt, $status );
531
532     if ( $status != 0 ) {
533         die ( "src directory copy failed!" );
534     }
535     return $dir;
536 }
537
538 /**
539  * Write iPXE config files based on value of given flags
540  *
541  * iPXE compile options are stored in src/config/*.h .
542  * We write out a config file for each set of options.
543  *
544  * @param string $config_dir directory to write .h files to
545  * @param array  $flags array of compile options for this build
546  *
547  * @return void
548  */
549 function write_ipxe_config_files ( $config_dir, $flags )
550 {
551     global $flag_table;
552
553     $cfgsecs = get_flag_cfgsecs ();
554
555     foreach ( $cfgsecs as $cfgsec ) {
556
557         $fname = $config_dir . "/" . $cfgsec . ".h";
558
559         $fp = fopen ( $fname, "wb" );
560         if ( $fp <= 0 ) {
561             die ( "Unable to open $fname file for output!" );
562         }
563
564         $ifdef_secname = "CONFIG_" . strtoupper ( $cfgsec ) . "_H";
565
566         fwrite ( $fp, "#ifndef ${ifdef_secname}\n" );
567         fwrite ( $fp, "#define ${ifdef_secname}\n" );
568         fwrite ( $fp, "#include <config/defaults.h>\n" );
569
570         foreach ( $flags as $key => $value ) {
571             // When the flag matches this section name, write it out
572             if ( $flag_table[$key]["cfgsec"] == $cfgsec ) {
573                 fwrite ( $fp, pprint_flag ( $key, $value ) . "\n" );
574             }
575         }
576         fwrite ( $fp, "#endif /* ${ifdef_secname} */\n" );
577         fclose ( $fp );
578     }
579 }
580
581 /**
582  * Output a string to a file
583  *
584  * Output a given string to a given pathname. The file will be created if
585  * necessary, and the string will replace the file's contents in all cases.
586  *
587  * @param string $fname pathname of file to output string to
588  * @param string $ftext text to output to file
589  *
590  * @return void
591  */
592 function write_file_from_string ( $fname, $ftext )
593 {
594         $fp = fopen ( $fname, "wb" );
595         if ( ! $fp ) {
596             die ( "Unable to open $fname file for output!" );
597         }
598         fwrite ( $fp, $ftext );
599         fclose ( $fp );
600 }
601
602 /**
603  * Delete a file or recursively delete a directory tree
604  *
605  * @param   string   $file_or_dir_name  name of file or directory to delete
606  * @return  bool     Returns TRUE on success, FALSE on failure
607  */
608 function rm_file_or_dir ( $file_or_dir_name )
609 {
610     if ( ! file_exists ( $file_or_dir_name ) ) {
611         return false;
612     }
613
614     if ( is_file ( $file_or_dir_name ) || is_link ( $file_or_dir_name ) ) {
615         return unlink ( $file_or_dir_name );
616     }
617
618     $dir = dir ( $file_or_dir_name );
619     while ( ( $dir_entry = $dir->read () ) !== false ) {
620
621         if ( $dir_entry == '.' || $dir_entry == '..') {
622             continue;
623         }
624         rm_file_or_dir ( $file_or_dir_name . '/' . $dir_entry );
625     }
626     $dir->close();
627
628     return rmdir ( $file_or_dir_name );
629 }
630
631 ////
632 // Debugging functions
633 ////
634
635 /**
636  * Emit html code to display given array of compile options (flags)
637  *
638  * @param array  $flags array of compile options for this build
639  *
640  * @return void
641  */
642 function show_flags ( $flags )
643 {
644     echo ( "\$flags contains " . count ( $flags ) . " elements:" . "<br>" );
645
646         foreach ( $flags as $key => $flag ) {
647         echo ( "\$flags[" . $key . "]=" . "\"$flag\"" . "<br>" );
648     }
649 }
650
651 /**
652  * Emit HTML code to display default array of compile options (flags)
653  *
654  * $flag_table contains default compile options and properties.  This
655  * routine outputs HTML code to display all properties of $flag_table.
656  *
657  * @return void
658  */
659 function dump_flag_table ()
660 {
661     global $flag_table;
662
663     echo ( "\$flag_table contains " . count ( $flag_table ) . " elements:" . "<br>" );
664
665         foreach ( $flag_table as $key => $props ) {
666         print ( "flag_table[" . $key . "] = " . "<br>" );
667
668                 foreach ( $props as $key2 => $props2 ) {
669             print ( "&nbsp;&nbsp;&nbsp;" . $key2 . " = " . $props2 . "<br>" );
670         }
671     }
672 }
673
674 // Parse src/bin/NIC file
675 list ( $nics, $roms ) = parse_nic_file ();
676
677 // For emacs:
678 // Local variables:
679 //  c-basic-offset: 4
680 //  c-indent-level: 4
681 //  tab-width: 4
682 // End:
683
684 ?>