diff --git a/.gitignore b/.gitignore index 991d7ab..9a9e017 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -Firmware +Firmware/* +ipxe/* +!.gitkeep +tmp +.DS_Store \ No newline at end of file diff --git a/Firmware/.gitkeep b/Firmware/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Firmware/place.holder b/Firmware/place.holder deleted file mode 100644 index 430d365..0000000 --- a/Firmware/place.holder +++ /dev/null @@ -1 +0,0 @@ -Git doesn't support empty directories diff --git a/fetchbios.pl b/fetchbios.pl index 58508cb..0502a6c 100755 --- a/fetchbios.pl +++ b/fetchbios.pl @@ -1,4 +1,10 @@ -#!/usr/bin/perl +#!/usr/bin/perl -W +# +# Rev: +# 2022.08.19 - Changed Table header positions, supermicro updated their website. +# +#use strict; +#use warnings; use HTML::TableExtract; use WWW::Mechanize; @@ -6,77 +12,249 @@ use HTML::Strip; use Date::Format; use Data::Dumper; +use Getopt::Std; +my %opt; +getopts('df:hv',\%opt); -sub trim($) +# CONF: Options available to configure. +no warnings qw{qw uninitialized}; +#my @tableheaders = qw ( Model Rev "Download ZIP" "Release Notes" "Part#" Description Name); +# 2022.08.19 - Less entries +my @tableheaders = qw ( Model Rev "Download ZIP 1" "Release Notes" Description); + + +# --- +my $o_filter = $opt{'f'} || 0; +my $o_debug = $opt{'d'} || 0; +my $o_verbose = $opt{'v'} || 0; +my $o_help = $opt{'h'} || 0; + + +if( $o_help ) +{ + print "$0 [-dvh] [-f ]\n"; + exit(0); + +} + + +# ----------------------------------------------------------------------------- +# SUB: Subroutines to assist in different aspects of the code +# +# +my %logLevel = ( + 'ERROR' => 1, + 'WARN' => 2, + 'INFO' => 3, + 'VERBOSE' => 4, + 'DEBUG' => 5 +); + +sub Log { - my $string = shift; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; + my( $level, @msg ) = @_; + my $tag = undef; + $level = $logLevel{$level}; + # Error = 1, Warn = 2, Info = 3, Verbose = 4, Debug = 5 + SWITCH: { + if( $level == 1 ) { $tag = "!"; last SWITCH; } + if( $level == 2 ) { $tag = "*"; last SWITCH; } + if( $level == 3 ) { $tag = "-"; last SWITCH; } + if( $level == 4 ) { $tag = " "; last SWITCH; } + if( $level == 5 ) { $tag = "D"; last SWITCH; } + } + + if( $level == 1 || $level == 2 ) + { + printf STDOUT ( " %s %s\n", $tag, join( '', @msg ) ); + } + if( ($o_verbose == 1 || $o_debug == 1) && ($level == 3 || $level == 4) ) + { + printf STDOUT ( " %s %s\n", $tag, join( '', @msg ) ); + } + if( $o_debug == 1 && $level == 5 ) + { + printf STDOUT ( " %s %s\n", $tag, join( '', @msg ) ); + } + + return undef; } -sub start { - my ($self, $tagname, $attr, $attrseq, $origtext) = @_; - if ($tagname eq 'a') { - print "URL found: ", $attr->{ href }, "\n"; - } + +sub trim($) +{ + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; } +# --------------------------------------------------------------------- chdir "Firmware" or die "Cannot chdir(\"Firmware\"): $!"; -my $hs = HTML::Strip->new(); - -my $url = "http://www.supermicro.nl/support/bios/"; -my @tableheaders = qw ( Model Name Type Rev "ZIP File" Description ); - -my $agent = WWW::Mechanize->new(); -$agent->get($url); - -print join(',', @tableheaders), "\n"; - -$te = new HTML::TableExtract( keep_html => 1, attribs => { id => 'ctl00_ctl00_ContentPlaceHolderMain_ContentPlaceHolderSupportMiddle_GridView1' } ); -$te->parse( $agent->content() ); - -foreach $ts ($te->table_states) { - foreach $row ($ts->rows) { - @Models = - sort( - grep(!/[^\w\s-+]/, - split(/\ /, - trim( - $hs->parse(@$row[0]) - ) - ) - ) - ); - - $Model = join('_', @Models); - $BIOS = trim($hs->parse( @$row[1])); - $Type = trim($hs->parse( @$row[2])); - $Rev = trim($hs->parse( @$row[3])); - $Rev =~ s/\ /_/; - ($ZipLink, $ZipText) = @$row[4] =~ /(ID=\d+)\".*\"\>(.*)\<\/font\>/; - next unless "$ZipLink" =~ /ID=/; - $BIOSPath = "$Model/$Type/$Rev/$ZipText"; - if (! -e $BIOSPath) { - mkdir "$Model"; - mkdir "$Model/$Type"; - mkdir "$Model/$Type/$Rev"; - open CL, '>>', "$Model/ChangeLog"; - open CL2, '>>', "ChangeLog"; - $Logline = time2str("%Y-%m-%d %H:%M:%S", time). " \"$Model/$Type/$Rev/$ZipText\"\n"; - print CL $Logline; - print CL2 $Logline; - print $Logline; - $BIOSURI = "http://www.supermicro.nl/support/resources/getfile.aspx?$ZipLink"; - $agent->get( $BIOSURI, ':content_file' => $BIOSPath ); - if ($Type eq "BIOS") { - system("../mkbiosimg.sh", "Firmware/$BIOSPath"); - } - } - } -} +# 1 = Intel, 2 = AMD +my @vendors = ( 1, 2 ); + +foreach ( @vendors ) +{ + # Sometimes this URL changes as well as the table structure. + my $url = "https://www.supermicro.com/support/resources/bios_ipmi.php?vendor=$_"; + + Log(INFO,"BIOS: Looking only for items which match $o_filter") if( $o_filter ); + + my $hs = HTML::Strip->new(); + + Log(VERBOSE,"Attemping to connect to $url"); + my $agent = WWW::Mechanize->new(); + $agent->get($url); + + if( $agent->status() != 200 ) # HTTP code 200, page OK + { + Log(ERROR, "Cannot access URL $url"); + exit(1); + } + + + Log(DEBUG,"HTML TableExtracting on class biosipmiTable"); + Log(DEBUG,"HTML Table headers to match: " . join(',', @tableheaders)); + my $te = new HTML::TableExtract( + keep_headers => 0, + keep_html => 1, + attribs => { + class => 'display' + } + ); + + Log(DEBUG,"HTML: Parse content"); + $te->parse( $agent->content() ); + + Log(DEBUG,"HTML: Table states - loop"); + #foreach $ts ($te->table_states) { + # + my $i = 0; + foreach $ts ($te->tables) + { + #use Data::Dumper; + # print Dumper($ts); + #Log(DEBUG,"LOOP: $ts"); + foreach $row ($ts->rows) + { + $i++; + #Log(DEBUG,"FOREACH ts: $row"); + #Log(DEBUG," -->: " . @$row[0] ); + # PROG: Parse through items in the table + # [0] Model + # [1] Revision of BIOS + # [2] Download ZIP file name + # [3] Release Notes + # [4] Part # + # [5] Description of item + # [6] Name of Motherboard + # 2022.08.19 changes + # [0] Model + # [1] Revision of BIOS + # [2] Download ZIP file name + # [3] Release Notes + # [4] Description of item + #if( $i == 5 ) { exit (); } + + Log(DEBUG, "FOREACH ROW: RAW => @{$row}"); + my @Models = split(/\s+/, trim($hs->parse( @$row[0]) )); + # i^-- split required due to non-whitespace parse from cpan module + my $Model = join("_", @Models); # C9X299-PGF_C9X299-RPGF + my $Rev = trim($hs->parse( @$row[1]) ); # R_1.2a + $Rev =~ s/\ /_/; + if( length($Rev) < 1 ) + { + $Rev = "UNKN"; + } + + my $ZipText = trim($hs->parse( @$row[2]) ); # C7Q2708_329.zip + my $Type = trim($hs->parse( @$row[4]) ); # BIOS/BMC ? + my $BIOS = trim($hs->parse( @$row[0]) ); # C9X299-PGF/RPGF + my ($ZipLink) = @$row[2] =~ /(SoftwareItemID=\d+)\".*\"\>(.*)\<\/a\>/; + $ZipLink = 0 if( not $ZipLink ); + if( $o_filter ) + { + next if( $Model !~ /$o_filter/ ); + } + + Log(DEBUG, "PARSE => Model : $Model / Rev: $Rev "); + Log(DEBUG, " Type : $Type / BIOS: $BIOS"); + Log(DEBUG, " ZipLink: $ZipLink / ZipText: $ZipText"); + Log(DEBUG, "--"); + Log(DEBUG, "--"); + + # exit if( $i == 8); # for debug, break out after [x] entries + + # PROG: If the type isn't BIOS then skip the entry move to next. + next unless ( $Type eq "BIOS" ); + Log(DEBUG, "DEBUG ROW PARSE => $Model / $Rev / $ZipLink / $ZipText / $Type / $BIOS"); + + + # PROG: If the ZipLink isn't a valid softwareItemId then skip it as well. + next unless ( "$ZipLink" =~ /SoftwareItemID=/ ); + + if( $o_debug == 1 ) + { + printf " => TYPE %-10s / Model %-20s / REV %-10s\n", $Type, $Model, $Rev; + printf " ZIP-ID: %-15s / FILE %15s\n", $ZipLink, $ZipText; + } + + # remove really really really long models + if (length($Model) > 254) { + Log(WARN,"WARN: Model stripped to 254 chars"); + $Model = substr($Model, 0, 254); + } + + # PROG: + # + # + my $BIOSPath = "$Model/$Type/$Rev/$ZipText"; + + if( ! -e $BIOSPath ) + { + Log(INFO,"BIOS: Creating path $BIOSPath"); + mkdir("$Model", 0755); + mkdir("$Model/$Type", 0755); + mkdir("$Model/$Type/$Rev", 0755); + + open CL, '>>', "$Model/ChangeLog"; + open CL2, '>>', "ChangeLog"; + $Logline = time2str("%Y-%m-%d %H:%M:%S", time) . ": $Model/$Type/$Rev/$ZipText\n"; + print CL $Logline; + print CL2 $Logline; + # print $Logline; + + $BIOSURI = "http://www.supermicro.com/support/resources/getfile.php?$ZipLink"; + + Log(VERBOSE, "FILE: Downloading $BIOS -> $ZipText"); + $agent->get( $BIOSURI, ':content_file' => $BIOSPath ); + + if( $agent->status() != 200 ) + { + Log(WARN,"WARN: Can't download $ZipLink / $ZipText, HTTP error: " . $agent->status()); + exit; + } else { + Log(INFO,"FILE: Complete, size(bytes) " . -s $BIOSPath ); + if( -s $BIOSPath < 4194304 ) + { + Log(ERROR,"FILE: Size is less than 4 MBytes"); + } + } + + # PROG: Build BIOS Image + Log(INFO,"BIOS: Building BIOS --> Firmware/$BIOSPath"); + system("../mkbiosimg.sh", "Firmware/$BIOSPath"); + system("../mkbiosimg-legacy.sh", "Firmware/$BIOSPath"); + } else { + Log(ERROR, "File already exists: $BIOSPath"); + } -chdir ".."; + } # foreach: ts->row + } # foreach: te->table +} # foreach: @vendors +chdir ".."; system("./mkpxecfg.sh"); +system("./mkpxecfg-legacy.sh"); diff --git a/ipxe/.gitkeep b/ipxe/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/memdisk b/memdisk new file mode 100644 index 0000000..70cb544 Binary files /dev/null and b/memdisk differ diff --git a/mkbiosimg-legacy.sh b/mkbiosimg-legacy.sh new file mode 100755 index 0000000..d759359 --- /dev/null +++ b/mkbiosimg-legacy.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# PROG: Build a bootable disk image for PXE booting +# + +set -e + +cd "$( dirname "${BASH_SOURCE[0]}" )" + +if [ -z "$1" ]; then + echo "Usage: $0 pathtozip" + exit +fi + +ZIPNAME="$1" +IMGNAME="`dirname \"$ZIPNAME\"`/`basename \"$ZIPNAME\" .zip`.img" + +FDOSNAME=mkbiosimg/fdboot.img + +#echo "==> MKFS.VFAT Create blank image" +if [ ! -x /sbin/mkfs.vfat ]; then + echo " [!] ERROR: Cannot execute mkfs.vfat, exiting !" + exit 1 +else + /sbin/mkfs.vfat -C "$IMGNAME" 65536 +fi + +#echo "==> SYS-FREEDOS: Copy FreeDOS boot sector info" +mkbiosimg/sys-freedos.pl --disk="$IMGNAME" + +#echo "==> 7Z: Expand fdBoot images accordingly. FDOSNAME=${FDOSNAME} ZIPNAME=${ZIPNAME}" +#echo "==> PWD: `pwd`" +rm -rf tmp +mkdir -p tmp/Update +7z x -otmp "$FDOSNAME" +7z x -otmp/Update "$ZIPNAME" + +#echo "==> MCOPY: Copy contents to a single directory IMGNAME ${IMGNAME} to tmp/\*" +#echo "==> PWD: `pwd`" +# -v = verbose, -s = recursive, -o = overwrite, -i = image +mcopy -s -o -i"$IMGNAME" tmp/* :: + +#echo "==> PIGZ: Compress the image accordingly as a final product IMGNAME=${IMGNAME}" +#echo "==> PWD: `pwd`" +pigz "$IMGNAME" +ls -la "$IMGNAME.gz" + diff --git a/mkbiosimg.sh b/mkbiosimg.sh index 5abf8ba..59b74d5 100755 --- a/mkbiosimg.sh +++ b/mkbiosimg.sh @@ -1,4 +1,8 @@ #!/bin/bash +# +# PROG: No longer making .img files, just unzippin! +# + set -e cd "$( dirname "${BASH_SOURCE[0]}" )" @@ -9,18 +13,12 @@ if [ -z "$1" ]; then fi ZIPNAME="$1" -IMGNAME="`dirname \"$ZIPNAME\"`/`basename \"$ZIPNAME\" .zip`.img" +DIRNAME="`dirname \"$ZIPNAME\"`/`basename \"$ZIPNAME\" .zip`" -FDOSNAME=mkbiosimg/fdboot.img +# Unzip the downloaded .zip in its proper directory, nothing fancy to see here. +unzip -jo $ZIPNAME -d$DIRNAME -/sbin/mkfs.vfat -C "$IMGNAME" 65536 -mkbiosimg/sys-freedos.pl --disk="$IMGNAME" -rm -rf tmp -mkdir -p tmp/Update -7z x -otmp "$FDOSNAME" -7z x -otmp/Update "$ZIPNAME" -mcopy -o -i"$IMGNAME" tmp/* :: +#replaced 7z with unzip after unpredictable behavior surrounding directories/files named identically to directories in SM releases. +#7z x $ZIPNAME -o$DIRNAME -pigz "$IMGNAME" -ls -la "$IMGNAME.gz" diff --git a/mkbiosimg/fdboot.img b/mkbiosimg/fdboot.img index ce7be36..4791c2d 100644 Binary files a/mkbiosimg/fdboot.img and b/mkbiosimg/fdboot.img differ diff --git a/mkpxecfg-legacy.sh b/mkpxecfg-legacy.sh new file mode 100755 index 0000000..d50bf6c --- /dev/null +++ b/mkpxecfg-legacy.sh @@ -0,0 +1,92 @@ +#!/bin/bash +set -x +set -e + +rm -rf tmp +mkdir tmp + +# Add menu header to start of BooterMicro's actual ipxe menu file. +echo '#!ipxe' > tmp/BooterMicro-LEGACY-MENUS.ipxe +echo ':start' >> tmp/BooterMicro-LEGACY-MENUS.ipxe +echo 'menu Bootermicro Firmware Updater/Installer - **LEGACY Mode**' >> tmp/BooterMicro-LEGACY-MENUS.ipxe + +# Dig through the ./Firmware directory to figure out what Boards/Revisions/BIOS/etc. exist and add entries for 'em +find ./Firmware -type f -name *.gz | sort | while IFS=/ read FOO Firmware BOARD BIOS VER FILE; do + if echo $BOARD | grep -q ^X1; then + GROUPLENGTH=4 + elif echo $BOARD | grep -q ^H1; then + GROUPLENGTH=4 + elif echo $BOARD | grep -q ^X; then + GROUPLENGTH=3 + elif echo $BOARD | grep -q ^H; then + GROUPLENGTH=3 + else + GROUPLENGTH=2 + fi + + GROUP="`echo $BOARD | cut -c1-$GROUPLENGTH`" + + # If a groups .ipxe files don't already exist, make the header info for the menu's, add 'em to the bootermicro menu, etc. upon first discovery. + if [ ! -e tmp/${GROUP}-LEGACY-MENU.ipxe ]; then + echo "#!ipxe" >> tmp/${GROUP}-LEGACY-MENU.ipxe + echo ":start" >> tmp/${GROUP}-LEGACY-MENU.ipxe + echo "menu Bootermicro Content for ${GROUP}" >> tmp/${GROUP}-LEGACY-MENU.ipxe + + LABELNAME=${i/tmp\//} + echo "item ${GROUP}-LEGACY ${GROUP} Category Firmware Updates" >> tmp/BooterMicro-LEGACY-MENUS.ipxe + echo ":${GROUP}-LEGACY" >> tmp/BooterMicro-LEGACY.ipxe + echo "chain ${GROUP}-LEGACY.ipxe --replace --autofree || goto start" >> tmp/BooterMicro-LEGACY.ipxe + echo "" >> tmp/BooterMicro-LEGACY.ipxe + fi + + ## Define individual firmwares per .zip file. A few .zip's are mangled, ignoring since they appear to be mostly old. + DIRECTORY="Firmware/${BOARD}/${BIOS}/${VER}/${FILE/.gz//*}" + echo ":${FILE/.img.gz/}" >> tmp/${GROUP}-LEGACY.ipxe + echo "item ${FILE/.img.gz/} ${BOARD}/${BIOS}/${VER}" >> tmp/${GROUP}-LEGACY-MENU.ipxe + + #for f in $DIRECTORY + #do + # FILENAME=${f// /%20} + # echo "imgfetch /BooterMicro/${FILENAME/ipxe/} || goto failed" >> tmp/${GROUP}-LEGACY.ipxe + #done + echo "initrd /BooterMicro/Firmware/${BOARD}/${BIOS}/${VER}/${FILE}" >> tmp/${GROUP}-LEGACY.ipxe + echo "chain /BooterMicro/memdisk raw || goto failed" >> tmp/${GROUP}-LEGACY.ipxe + + echo "goto start" >> tmp/${GROUP}-LEGACY.ipxe + echo "" >> tmp/${GROUP}-LEGACY.ipxe +done + + +# Add the menu footer data to the menu portions of the file. +for i in tmp/*-LEGACY-MENU.ipxe; do + echo "item" >> ${i} + echo "item back --key 0x08 Return to previous menu..." >> ${i} + echo "choose selected && goto \${selected} || goto start" >> ${i} + echo ":back" >> ${i} + echo "exit" >> ${i} +# echo "chain BooterMicro-LEGACY.ipxe --replace --autofree || goto start" >> ${i} +done + +# Drop final footer into Bootermicro-LEGACY.ipxe file (done separately, to make sure its done after all other entries inserted) +echo "item" >> tmp/BooterMicro-LEGACY-MENUS.ipxe +echo "item back --key 0x08 Return to previous menu..." >> tmp/BooterMicro-LEGACY-MENUS.ipxe +echo "choose selected && goto \${selected} || goto start" >> tmp/BooterMicro-LEGACY-MENUS.ipxe +echo ":back" >> tmp/BooterMicro-LEGACY-MENUS.ipxe +echo "exit" >> tmp/BooterMicro-LEGACY-MENUS.ipxe +echo "" >> tmp/BooterMicro-LEGACY-MENUS.ipxe +mv tmp/BooterMicro-LEGACY-MENUS.ipxe tmp/BooterMicro-LEGACY-MENU.ipxe + +# Merge the MENU and plain [label] files back together, so the menu block is at the top, and the labels are below. +for x in tmp/*-LEGACY-MENU.ipxe; do + cat ${x/-MENU/} >> ${x} + mv ${x} ${x/-MENU/} +done +echo "FINAL CLEANUP" + +# worded as ../BooterMicro/ipxe to prevent potential accidental nuking of ipxe during dev. +#rm -rf ../BooterMicro/ipxe +#mkdir ../BooterMicro/ipxe +## Skipped on legacy script, it runs second, cant have it wiping out the files UEFI just put in there. + +mv tmp/* ipxe + diff --git a/mkpxecfg.sh b/mkpxecfg.sh index 170be6d..ba5c2ee 100755 --- a/mkpxecfg.sh +++ b/mkpxecfg.sh @@ -1,43 +1,87 @@ #!/bin/bash - set -x set -e rm -rf tmp mkdir tmp -pushd tmp -find ../Firmware -type f -name *.img.gz | sort | while IFS=/ read FOO Firmware BOARD bios VER FILE; do - if echo $BOARD | grep -q ^X10; then + +# Add menu header to start of BooterMicro's actual ipxe menu file. +echo '#!ipxe' > tmp/BooterMicro-MENUS.ipxe +echo ':start' >> tmp/BooterMicro-MENUS.ipxe +echo 'menu Bootermicro Firmware Updater/Installer - **UEFI Mode**' >> tmp/BooterMicro-MENUS.ipxe + +# Dig through the ./Firmware directory to figure out what Boards/Revisions/BIOS/etc. exist and add entries for 'em +find ./Firmware -type f -name *.zip | sort | while IFS=/ read FOO Firmware BOARD BIOS VER FILE; do + if echo $BOARD | grep -q ^X1; then + GROUPLENGTH=4 + elif echo $BOARD | grep -q ^H1; then GROUPLENGTH=4 elif echo $BOARD | grep -q ^X; then GROUPLENGTH=3 + elif echo $BOARD | grep -q ^H; then + GROUPLENGTH=3 else GROUPLENGTH=2 fi - GROUP=`echo $BOARD | cut -c1-$GROUPLENGTH` - SMNAME=${FILE/.img.gz/} + GROUP="`echo $BOARD | cut -c1-$GROUPLENGTH`" - if [ ! -e ${GROUP}.cfg ]; then - echo "MENU BEGIN $GROUP" > ${GROUP}.cfg + # If a groups .ipxe files don't already exist, make the header info for the menu's, add 'em to the bootermicro menu, etc. upon first discovery. + if [ ! -e tmp/${GROUP}-MENU.ipxe ]; then + echo "#!ipxe" >> tmp/${GROUP}-MENU.ipxe + echo ":start" >> tmp/${GROUP}-MENU.ipxe + echo "menu Bootermicro Content for ${GROUP}" >> tmp/${GROUP}-MENU.ipxe + + LABELNAME=${i/tmp\//} + echo "item ${GROUP} ${GROUP} Category Firmware Updates" >> tmp/BooterMicro-MENUS.ipxe + echo ":${GROUP}" >> tmp/BooterMicro.ipxe + echo "chain ${GROUP}.ipxe --replace --autofree || goto start" >> tmp/BooterMicro.ipxe + echo "" >> tmp/BooterMicro.ipxe fi - echo "LABEL $SMNAME" >> ${GROUP}.cfg - echo "MENU LABEL Supermicro $BOARD ($VER) ($SMNAME)" >> ${GROUP}.cfg - echo "LINUX memdisk" >> ${GROUP}.cfg - echo "INITRD BooterMicro/Firmware/$BOARD/$bios/$VER/$FILE" >> ${GROUP}.cfg - echo "" >> ${GROUP}.cfg + ## Define individual firmwares per .zip file. A few .zip's are mangled, ignoring since they appear to be mostly old. + DIRECTORY="Firmware/${BOARD}/${BIOS}/${VER}/${FILE/.zip//*}" + echo ":${FILE/.zip/}" >> tmp/${GROUP}.ipxe + echo "item ${FILE/.zip/} ${BOARD}/${BIOS}/${VER}" >> tmp/${GROUP}-MENU.ipxe + for f in $DIRECTORY + do + FILENAME=${f// /%20} + echo "imgfetch /BooterMicro/${FILENAME/ipxe/} || goto failed" >> tmp/${GROUP}.ipxe + done + echo "imgfetch /BooterMicro/startup.nsh || goto failed" >> tmp/${GROUP}.ipxe + echo "chain /BooterMicro/ramdisk-shell.efi || goto failed" >> tmp/${GROUP}.ipxe + echo "goto start" >> tmp/${GROUP}.ipxe + echo "" >> tmp/${GROUP}.ipxe done -echo 'MENU BEGIN Supermicro Motherboard BIOS/UEFI updates' > ../BooterMicro.cfg -for i in *.cfg; do - echo "MENU END" >> $i - echo "INCLUDE pxelinux.cfg/BooterMicro/$i" >> ../BooterMicro.cfg + +# Add the menu footer data to the menu portions of the file. +for i in tmp/*-MENU.ipxe; do + echo "item" >> ${i} + echo "item back --key 0x08 Return to previous menu..." >> ${i} + echo "choose selected && goto \${selected} || goto start" >> ${i} + echo ":back" >> ${i} + echo "exit" >> ${i} +# echo "chain BooterMicro.ipxe --replace --autofree || goto start" >> ${i} +done + +# Drop final footer into Bootermicro.ipxe file (done separately, to make sure its done after all other entries inserted) +echo "item" >> tmp/BooterMicro-MENUS.ipxe +echo "item back --key 0x08 Return to previous menu..." >> tmp/BooterMicro-MENUS.ipxe +echo "choose selected && goto \${selected} || goto start" >> tmp/BooterMicro-MENUS.ipxe +echo ":back" >> tmp/BooterMicro-MENUS.ipxe +echo "exit" >> tmp/BooterMicro-MENUS.ipxe +echo "" >> tmp/BooterMicro-MENUS.ipxe +mv tmp/BooterMicro-MENUS.ipxe tmp/BooterMicro-MENU.ipxe + +# Merge the MENU and plain [label] files back together, so the menu block is at the top, and the labels are below. +for x in tmp/*-MENU.ipxe; do + cat ${x/-MENU/} >> ${x} + mv ${x} ${x/-MENU/} done -echo 'MENU END' >> ../BooterMicro.cfg -popd +# worded as ../BooterMicro/ipxe to prevent potential accidental nuking of ipxe during dev. +rm -rf ../BooterMicro/ipxe +mkdir ../BooterMicro/ipxe +mv tmp/* ipxe -rm -rf ../pxelinux.cfg/BooterMicro -mv tmp ../pxelinux.cfg/BooterMicro -mv BooterMicro.cfg ../pxelinux.cfg/BooterMicro.cfg diff --git a/ramdisk-shell.efi b/ramdisk-shell.efi new file mode 100644 index 0000000..0f39743 Binary files /dev/null and b/ramdisk-shell.efi differ diff --git a/startup.nsh b/startup.nsh new file mode 100755 index 0000000..0c6851b --- /dev/null +++ b/startup.nsh @@ -0,0 +1,5 @@ +load -b +mkramdisk +cp fs0:* ram0: +ram0: +rm startup.nsh