From d3e41ea1efffc8fa0f96c8239d154dbbe3ee29b4 Mon Sep 17 00:00:00 2001 From: Stewart Smith Date: Thu, 14 Dec 2017 11:04:38 +1100 Subject: [PATCH] Use ffspart alongside hostboot code to generate pnors Initially, we build the CSV input file for ffspart from the XML and feed it into ffspart. That way we can diff the resulting constructed image to ensure we're producing binary identical output. This is nearly all Cyril's work, with hints/fixes by Sam. Based-off-of-work-by: Cyril Bur Signed-off-by: Stewart Smith --- create_pnor_image.pl | 167 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/create_pnor_image.pl b/create_pnor_image.pl index 51ea988..3edd3c3 100755 --- a/create_pnor_image.pl +++ b/create_pnor_image.pl @@ -26,6 +26,21 @@ my $memddata_binary_filename = ""; my $hdat_binary_filename = ""; +my $SEPARATOR = ","; + +sub write_header_csv { + my ($csv, $num, $base, $flags) = @_; + my $S = $SEPARATOR; + printf $csv "\@%d${S}0x%08x${S}%s\n", $num, $base, $flags; +} + +sub write_partition_csv { + my ($csv, $name, $base, $size, $flags, $tocs, $file) = @_; + my $S = $SEPARATOR; + printf $csv "%s${S}0x%08x${S}0x%08x${S}%s${S}%s${S}%s\n", + $name, $base, $size, $flags, $tocs, $file; +} + while (@ARGV > 0){ $_ = $ARGV[0]; chomp($_); @@ -169,27 +184,178 @@ $build_pnor_command .= " --binFile_SECBOOT $scratch_dir/secboot.bin.ecc"; $build_pnor_command .= " --binFile_VERSION $scratch_dir/openpower_pnor_version.bin"; $build_pnor_command .= " --binFile_IMA_CATALOG $scratch_dir/ima_catalog.bin.ecc"; +my %filenames = ( + 'SBE' => "$scratch_dir/$sbe_binary_filename", + 'HBB' => "$scratch_dir/hostboot.header.bin.ecc", + 'HBI' => "$scratch_dir/hostboot_extended.header.bin.ecc", + 'HBRT' => "$scratch_dir/hostboot_runtime.header.bin.ecc", + 'HBEL' => "$scratch_dir/hbel.bin.ecc", + 'GUARD' => "$scratch_dir/guard.bin.ecc", + 'PAYLOAD' => "$payload", + 'BOOTKERNEL' => "$bootkernel", + 'NVRAM' => "$scratch_dir/nvram.bin", + 'MVPD' => "$scratch_dir/mvpd_fill.bin.ecc", + 'DJVPD' => "$scratch_dir/djvpd_fill.bin.ecc", + 'CVPD' => "$scratch_dir/cvpd.bin.ecc", + 'ATTR_TMP' => "$scratch_dir/attr_tmp.bin.ecc", + 'ATTR_PERM' => "$scratch_dir/attr_perm.bin.ecc", + 'OCC' => "$occ_binary_filename.ecc", + 'FIRDATA' => "$scratch_dir/firdata.bin.ecc", + 'CAPP' => "$scratch_dir/cappucode.bin.ecc", + 'SECBOOT' => "$scratch_dir/secboot.bin.ecc", + 'VERSION' => "$openpower_version_filename", + 'IMA_CATALOG' => "$scratch_dir/ima_catalog.bin.ecc" +); + +if ($does_HBD_RW_exist eq 0) { + $filenames{'HBD'} = "$scratch_dir/$targeting_binary_filename"; +} else { + $filenames{'HBD'} = "$scratch_dir/$targeting_RO_binary_filename"; + $filenames{'HBD_RW'} = "$scratch_dir/$targeting_RW_binary_filename"; +} if ($release eq "p9"){ $build_pnor_command .= " --binFile_WOFDATA $wofdata_binary_filename" if -e $wofdata_binary_filename; $build_pnor_command .= " --binFile_MEMD $memddata_binary_filename" if -e $memddata_binary_filename; $build_pnor_command .= " --binFile_HDAT $hdat_binary_filename" if -e $hdat_binary_filename; + #Sigh + $filenames{'WOFDATA'} = "$wofdata_binary_filename" if -e $wofdata_binary_filename; + $filenames{'MEMD'} = "$memddata_binary_filename" if -e $memddata_binary_filename; + $filenames{'HDAT'} = "$hdat_binary_filename" if -e $hdat_binary_filename; } if ($release eq "p8"){ $build_pnor_command .= " --binFile_SBEC $scratch_dir/$sbec_binary_filename"; $build_pnor_command .= " --binFile_WINK $scratch_dir/$wink_binary_filename"; + $filenames{'SBEC'} = "$scratch_dir/$sbec_binary_filename"; + $filenames{'WINK'} = "$scratch_dir/$wink_binary_filename"; } else { $build_pnor_command .= " --binFile_SBKT $scratch_dir/SBKT.bin"; $build_pnor_command .= " --binFile_HCODE $scratch_dir/$wink_binary_filename"; $build_pnor_command .= " --binFile_HBBL $scratch_dir/hbbl.bin.ecc"; $build_pnor_command .= " --binFile_RINGOVD $scratch_dir/ringOvd.bin"; $build_pnor_command .= " --binFile_HB_VOLATILE $scratch_dir/guard.bin.ecc"; + $filenames{'SBKT'} = "$scratch_dir/SBKT.bin"; + $filenames{'HCODE'} = "$scratch_dir/$wink_binary_filename"; + $filenames{'HBBL'} = "$scratch_dir/hbbl.bin.ecc"; + $filenames{'RINGOVD'} = "$scratch_dir/ringOvd.bin"; + $filenames{'HB_VOLATILE'} = "$scratch_dir/guard.bin.ecc"; } $build_pnor_command .= " --fpartCmd \"fpart\""; $build_pnor_command .= " --fcpCmd \"fcp\""; print "###############################"; run_command("$build_pnor_command"); +#Generate the CSV +my $ref = XMLin("$xml_layout_file", ForceArray => ['metadata', 'section'], SuppressEmpty => undef); +my $csv; +open($csv, ">", "$scratch_dir/pnor_layout.csv") or die "Can't open > $scratch_dir/pnor_layout.csv $!"; + +if (${$ref->{'metadata'}}[0]->{'arrangement'} ne "A-D-B") { + printf STDERR "Found '%s' expecting 'A-D-B'\n", + ${$ref->{'metadata'}}[0]->{'arrangement'}; + die "Unexpected tag"; +} + +my $image_size = hex (${$ref->{'metadata'}}[0]->{'imageSize'}); +my $block_size = hex (${$ref->{'metadata'}}[0]->{'blockSize'}); +my $block_count = $image_size / $block_size; +my $toc_size = hex (${$ref->{'metadata'}}[0]->{'tocSize'}); +my $side_string = "0"; +my $side_count = keys(%{${$ref->{'metadata'}}[0]->{'side'}}); + +#Please don't ask me why +my $part_offset = 0; +if ($release eq "p9") { + $part_offset = $block_size; +} + +if (@{$ref->{'metadata'}} == 1) { + if ($side_count == 1) { + write_header_csv $csv, 0, 0, ""; + write_header_csv $csv, 1, $image_size - $toc_size - $part_offset, ""; + $side_string = "01"; + } elsif ($side_count == 2) { + write_header_csv $csv, 0, 0, ""; + write_header_csv $csv, 1, ($image_size / 2) - $toc_size - $part_offset, ""; + write_header_csv $csv, 2, ($image_size / 2), "G"; + write_header_csv $csv, 3, $image_size - $toc_size - $part_offset, "G"; + $side_string = "0123"; + } else { + printf STDERR "Sides not 1 or 2, total: %d\n", $side_count; + die "Unexpected number of sides\n"; + } +} else { + printf STDERR "Found %d tags\n", @{$ref->{'metadata'}}; + die "There shouldn't be more than one \n"; +} + +foreach my $section (@{$ref->{'section'}}) { + my $name = $section->{'eyeCatch'}; + my $base = hex($section->{'physicalOffset'}); + my $size = hex($section->{'physicalRegionSize'}); + my $flags = ""; + $flags .= 'E' if (exists($section->{'ecc'})); + $flags .= 'L' if (exists($section->{'sha512Version'})); + $flags .= 'F' if (exists($section->{'reprovision'})); + $flags .= 'I' if (exists($section->{'sha512perEC'})); + $flags .= 'P' if (exists($section->{'preserved'})); + $flags .= 'R' if (exists($section->{'readOnly'})); + $flags .= 'C' if (exists($section->{'clearOnEccErr'})); + $flags .= 'V' if (exists($section->{'volatile'})); + my $side = ""; + if (exists($section->{'side'}) and $section->{'side'} ne "sideless") { + $side = "01" if ($section->{'side'} eq "A"); + $side = "23" if ($section->{'side'} eq "B"); + } else { + $side = $side_string; #Either "sideless" or no sides at all so all 0 is good + } + my $file = "/dev/zero"; + if (exists($filenames{$section->{'eyeCatch'}})) { + $file = "$filenames{$section->{'eyeCatch'}}"; + } else { + print STDERR "# Assuming partition $section->{'eyeCatch'} is blank\n"; + } + write_partition_csv $csv, $name, $base, $size, $flags, $side, $file; +} + +#BACKUP_PART should exist in the TOC before OTHER_SIDE. ffspart will +#respect the order of the CSV + +#Add the other side and backup part partitions +if ($side_count == 2) { + write_partition_csv $csv, "BACKUP_PART", + ($image_size / 2) - $toc_size - $part_offset, $toc_size, "B", 0, "/dev/zero"; + write_partition_csv $csv, "BACKUP_PART", + $image_size - $toc_size - $part_offset, $toc_size, "B", 2, "/dev/zero"; + + #BACKUP_PART for OTHER_SIDEs + write_partition_csv $csv, "BACKUP_PART", 0, $toc_size, "B", 1, "/dev/zero"; + write_partition_csv $csv, "BACKUP_PART", $image_size / 2, $toc_size, + "B", 3, "/dev/zero"; + + write_partition_csv $csv, "OTHER_SIDE", $image_size / 2, $toc_size, + "B", 0, "/dev/zero"; + write_partition_csv $csv, "OTHER_SIDE", 0, $toc_size, "B", 2, "/dev/zero"; + + #OTHER_SIDEs for BACKUP_PARTs + write_partition_csv $csv, "OTHER_SIDE", $image_size - $toc_size - $part_offset, + $toc_size, "B", 1, "/dev/zero"; + write_partition_csv $csv, "OTHER_SIDE", + ($image_size / 2) - $toc_size - $part_offset, + $toc_size, "B", 3, "/dev/zero"; +} else { + #Don't forget those pesky backup parts for the regular TOC + write_partition_csv $csv, "BACKUP_PART", + $image_size - $toc_size - $part_offset, $toc_size, + "B", 0, "/dev/zero"; + write_partition_csv $csv, "BACKUP_PART", 0, $toc_size, "B", 1, "/dev/zero"; +} + + +#ffspart should really learn to make its own output file +run_command("touch $outdir/ffspart.pnor"); +run_command("ffspart -e -s $block_size -c $block_count -i $scratch_dir/pnor_layout.csv -p $outdir/ffspart.pnor"); + #END MAIN #------------------------------------------------------------------------- sub usage { @@ -208,7 +374,6 @@ sub parse_config_file { } - #trim_string takes one string as input, trims leading and trailing whitespace # before returning that string sub trim_string {