Commit 0677d0d9 authored by Thomas Altenbach's avatar Thomas Altenbach Committed by David Brown
Browse files

sim: Fix largest image computation for swap-move and swap-offset



For the swap-move and swap-offset strategies, the computation of the
largest image size was not taking taking into account the padding that
is needed when using those strategies. Due to this limitation, the
simulator is currently using hardcoded image sizes, smaller than the
maximum possible size, when running tests for the swap-move or
swap-offset strategies. This commit fixes the maximum image size
computation for those strategies.

Signed-off-by: default avatarThomas Altenbach <thomas.altenbach@legrand.com>
parent 2e605191
Loading
Loading
Loading
Loading
+71 −55
Original line number Diff line number Diff line
@@ -234,21 +234,21 @@ impl ImagesBuilder {

            let (primaries,upgrades) =  if img_manipulation == ImageManipulation::CorruptHigherVersionImage && !higher_version_corrupted {
                higher_version_corrupted = true;
               let prim =  install_image(&mut flash, &self.areadesc, &slots[0],
                    maximal(42784), &ram, &*dep, ImageManipulation::None, Some(0), false);
                let prim =  install_image(&mut flash, &self.areadesc, &slots, 0,
                    maximal(42784), &ram, &*dep, ImageManipulation::None, Some(0));
                let upgr   = match deps.depends[image_num] {
                    DepType::NoUpgrade => install_no_image(),
                    _ => install_image(&mut flash, &self.areadesc, &slots[1],
                        maximal(46928), &ram, &*dep, ImageManipulation::BadSignature, Some(0), true)
                    _ => install_image(&mut flash, &self.areadesc, &slots, 1,
                        maximal(46928), &ram, &*dep, ImageManipulation::BadSignature, Some(0))
                };
                (prim, upgr)
            } else {
                let prim = install_image(&mut flash, &self.areadesc, &slots[0],
                    maximal(42784), &ram, &*dep, img_manipulation, Some(0), false);
                let prim = install_image(&mut flash, &self.areadesc, &slots, 0,
                    maximal(42784), &ram, &*dep, img_manipulation, Some(0));
                let upgr = match deps.depends[image_num] {
                        DepType::NoUpgrade => install_no_image(),
                        _ => install_image(&mut flash, &self.areadesc, &slots[1],
                            maximal(46928), &ram, &*dep, img_manipulation, Some(0), true)
                        _ => install_image(&mut flash, &self.areadesc, &slots, 1,
                            maximal(46928), &ram, &*dep, img_manipulation, Some(0))
                    };
                (prim, upgr)
            };
@@ -298,10 +298,10 @@ impl ImagesBuilder {
        let ram = self.ram.clone(); // TODO: Avoid this clone.
        let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
            let dep = BoringDep::new(image_num, &NO_DEPS);
            let primaries = install_image(&mut bad_flash, &self.areadesc, &slots[0],
                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0), false);
            let upgrades = install_image(&mut bad_flash, &self.areadesc, &slots[1],
                maximal(41928), &ram, &dep, ImageManipulation::BadSignature, Some(0), true);
            let primaries = install_image(&mut bad_flash, &self.areadesc, &slots, 0,
                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
            let upgrades = install_image(&mut bad_flash, &self.areadesc, &slots, 1,
                maximal(41928), &ram, &dep, ImageManipulation::BadSignature, Some(0));
            OneImage {
                slots,
                primaries,
@@ -321,10 +321,10 @@ impl ImagesBuilder {
        let ram = self.ram.clone(); // TODO: Avoid this clone.
        let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
            let dep = BoringDep::new(image_num, &NO_DEPS);
            let primaries = install_image(&mut bad_flash, &self.areadesc, &slots[0],
                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0), false);
            let upgrades = install_image(&mut bad_flash, &self.areadesc, &slots[1],
                ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0), true);
            let primaries = install_image(&mut bad_flash, &self.areadesc, &slots, 0,
                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
            let upgrades = install_image(&mut bad_flash, &self.areadesc, &slots, 1,
                ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
            OneImage {
                slots,
                primaries,
@@ -344,8 +344,8 @@ impl ImagesBuilder {
        let ram = self.ram.clone(); // TODO: Avoid this clone.
        let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
            let dep = BoringDep::new(image_num, &NO_DEPS);
            let primaries = install_image(&mut flash, &self.areadesc, &slots[0],
                maximal(32784), &ram, &dep,ImageManipulation::None, Some(0), false);
            let primaries = install_image(&mut flash, &self.areadesc, &slots, 0,
                maximal(32784), &ram, &dep,ImageManipulation::None, Some(0));
            let upgrades = install_no_image();
            OneImage {
                slots,
@@ -367,8 +367,8 @@ impl ImagesBuilder {
        let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
            let dep = BoringDep::new(image_num, &NO_DEPS);
            let primaries = install_no_image();
            let upgrades = install_image(&mut flash, &self.areadesc, &slots[1],
                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0), true);
            let upgrades = install_image(&mut flash, &self.areadesc, &slots, 1,
                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
            OneImage {
                slots,
                primaries,
@@ -389,8 +389,8 @@ impl ImagesBuilder {
        let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
            let dep = BoringDep::new(image_num, &NO_DEPS);
            let primaries = install_no_image();
            let upgrades = install_image(&mut flash, &self.areadesc, &slots[1],
                ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0), true);
            let upgrades = install_image(&mut flash, &self.areadesc, &slots, 1,
                ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
            OneImage {
                slots,
                primaries,
@@ -411,10 +411,10 @@ impl ImagesBuilder {
        let ram = self.ram.clone(); // TODO: Avoid this clone.
        let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
            let dep = BoringDep::new(image_num, &NO_DEPS);
            let primaries = install_image(&mut flash, &self.areadesc, &slots[0],
                maximal(32784), &ram, &dep,  ImageManipulation::None, security_cnt, false);
            let upgrades = install_image(&mut flash, &self.areadesc, &slots[1],
                maximal(41928), &ram, &dep, ImageManipulation::None, security_cnt.map(|v| v + 1), true);
            let primaries = install_image(&mut flash, &self.areadesc, &slots, 0,
                maximal(32784), &ram, &dep,  ImageManipulation::None, security_cnt);
            let upgrades = install_image(&mut flash, &self.areadesc, &slots, 1,
                maximal(41928), &ram, &dep, ImageManipulation::None, security_cnt.map(|v| v + 1));
            OneImage {
                slots,
                primaries,
@@ -1819,19 +1819,52 @@ fn image_largest_trailer(dev: &dyn Flash, areadesc: &AreaDesc, slot: &SlotInfo)
            trailer
}

// Computes the padding required in the primary or secondary slot to be able to perform an upgrade.
// This is needed only for the swap-move and swap-offset upgrade strategies.
fn required_slot_padding(dev: &dyn Flash) -> usize {
    let mut required_padding = 0;

    if Caps::SwapUsingMove.present() || Caps::SwapUsingOffset.present() {
        // Assumes equally-sized sectors
        let sector_size = dev.sector_iter().next().unwrap().size;

        required_padding = sector_size;
    };

    required_padding
}

// Computes the largest possible firmware image size, not including the header and TLV area.
fn compute_largest_image_size(dev: &dyn Flash, areadesc: &AreaDesc, slots: &[SlotInfo],
                              slot_ind: usize, hdr_size: usize, tlv: &dyn ManifestGen) -> usize {
    let slot_len = if Caps::SwapUsingOffset.present() {
        slots[1].len
    } else {
        slots[0].len
    };

    let trailer = image_largest_trailer(dev, areadesc, &slots[slot_ind]);
    let padding = required_slot_padding(dev);
    let tlv_len = tlv.estimate_size();
    info!("slot: 0x{:x}, HDR: 0x{:x}, trailer: 0x{:x}, tlv_len: 0x{:x}, padding: 0x{:x}",
        slot_len, hdr_size, trailer, tlv_len, padding);

    slot_len - hdr_size - trailer - tlv_len - padding
}

/// Install a "program" into the given image.  This fakes the image header, or at least all of the
/// fields used by the given code.  Returns a copy of the image that was written.
fn install_image(flash: &mut SimMultiFlash, areadesc: &AreaDesc, slot: &SlotInfo, len: ImageSize,
                 ram: &RamData,
                 deps: &dyn Depender, img_manipulation: ImageManipulation, security_counter:Option<u32>, secondary_slot:bool) -> ImageData {
fn install_image(flash: &mut SimMultiFlash, areadesc: &AreaDesc, slots: &[SlotInfo],
                 slot_ind: usize, len: ImageSize, ram: &RamData,
                 deps: &dyn Depender, img_manipulation: ImageManipulation, security_counter:Option<u32>) -> ImageData {
    let slot = &slots[slot_ind];
    let mut offset = slot.base_off;
    let slot_len = slot.len;
    let dev_id = slot.dev_id;
    let dev = flash.get_mut(&dev_id).unwrap();

    let mut tlv: Box<dyn ManifestGen> = Box::new(make_tlv());

    if Caps::SwapUsingOffset.present() && secondary_slot {
    if Caps::SwapUsingOffset.present() && slot_ind == 1 {
        let sector_size = dev.sector_iter().next().unwrap().size as usize;
        offset += sector_size;
    }
@@ -1863,30 +1896,13 @@ fn install_image(flash: &mut SimMultiFlash, areadesc: &AreaDesc, slot: &SlotInfo

    let len = match len {
        ImageSize::Given(size) => size,
        ImageSize::Largest => {
            let trailer = image_largest_trailer(dev, &areadesc, &slot);
            let tlv_len = tlv.estimate_size();
            info!("slot: 0x{:x}, HDR: 0x{:x}, trailer: 0x{:x}",
                slot_len, HDR_SIZE, trailer);
            slot_len - HDR_SIZE - trailer - tlv_len
        },
        ImageSize::Largest => compute_largest_image_size(dev, areadesc, slots, slot_ind,
                                                         HDR_SIZE, tlv.as_ref()),
        ImageSize::Oversized => {
            let trailer = image_largest_trailer(dev, &areadesc, &slot);
            let tlv_len = tlv.estimate_size();
            let mut sector_offset = 0;

            if Caps::SwapUsingOffset.present() && secondary_slot {
                // This accounts for when both slots have the same size, it will not work where
                // the second slot is one sector larger than the primary
                sector_offset = dev.sector_iter().next().unwrap().size as usize;
            let largest_img_sz = compute_largest_image_size(dev, areadesc, slots, slot_ind,
                                                            HDR_SIZE, tlv.as_ref());
            largest_img_sz + dev.align()
        }

            info!("slot: 0x{:x}, HDR: 0x{:x}, trailer: 0x{:x}",
                slot_len, HDR_SIZE, trailer);

            slot_len - HDR_SIZE - trailer - tlv_len - sector_offset + dev.align()
        }

    };

    // Generate a boot header.  Note that the size doesn't include the header.
@@ -1995,7 +2011,7 @@ fn install_image(flash: &mut SimMultiFlash, areadesc: &AreaDesc, slot: &SlotInfo

            enc_copy = Some(enc);

            dev.erase(offset, slot_len).unwrap();
            dev.erase(offset, slot.len).unwrap();
        } else {
            enc_copy = None;
        }
@@ -2020,7 +2036,7 @@ fn install_image(flash: &mut SimMultiFlash, areadesc: &AreaDesc, slot: &SlotInfo
        let enc_copy: Option<Vec<u8>>;

        if is_encrypted {
            dev.erase(offset, slot_len).unwrap();
            dev.erase(offset, slot.len).unwrap();

            dev.write(offset, &encbuf).unwrap();