Skip to content

Commit 10e6d55

Browse files
committed
COSI output image type support.
1 parent 3fabd8c commit 10e6d55

File tree

5 files changed

+269
-62
lines changed

5 files changed

+269
-62
lines changed

toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput.go

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package imagecustomizerlib
66
import (
77
"fmt"
88
"os"
9+
"path"
910
"path/filepath"
1011
"regexp"
1112
"slices"
@@ -102,12 +103,14 @@ func outputArtifacts(items []imagecustomizerapi.OutputArtifactsItemType,
102103
signedName := replaceSuffix(entry.Name(), ".unsigned.efi", ".signed.efi")
103104
source := "./" + signedName
104105
unsignedSource := "./" + entry.Name()
105-
destinationName := replaceSuffix(entry.Name(), ".unsigned.efi", ".efi")
106+
// ToDo: use default unsigned name for UKI.
107+
//
108+
// destinationName := replaceSuffix(entry.Name(), ".unsigned.efi", ".efi")
106109

107110
outputArtifactsMetadata = append(outputArtifactsMetadata, imagecustomizerapi.InjectArtifactMetadata{
108111
Partition: partition,
109112
Source: source,
110-
Destination: filepath.Join("/", UkiOutputDir, destinationName),
113+
Destination: filepath.Join("/", UkiOutputDir, entry.Name()),
111114
UnsignedSource: unsignedSource,
112115
})
113116
}
@@ -282,6 +285,48 @@ func InjectFiles(buildDir string, baseConfigPath string, inputImageFile string,
282285
return err
283286
}
284287

288+
// ToDo: prepare COSI image converting.
289+
//
290+
rootfsPartition, err := findRootfsPartition(diskPartitions, buildDir)
291+
if err != nil {
292+
return fmt.Errorf("failed to find rootfs partition:\n%w", err)
293+
}
294+
295+
fstabEntries, osRelease, err := readFstabEntriesFromRootfs(rootfsPartition, diskPartitions, buildDir)
296+
if err != nil {
297+
return fmt.Errorf("failed to read fstab entries from rootfs partition:\n%w", err)
298+
}
299+
300+
_, partUuidToFstabEntry, baseImageVerityMetadata, err := fstabEntriesToMountPoints(fstabEntries, diskPartitions, buildDir)
301+
if err != nil {
302+
return fmt.Errorf("failed to find mount info for fstab file entries:\n%w", err)
303+
}
304+
305+
logger.Log.Debugf("Resolved partUuidToFstabEntry map:")
306+
for partuuid, entry := range partUuidToFstabEntry {
307+
logger.Log.Debugf(" %s → target=%s, source=%s, fsType=%s, options=%s, fsOptions=%s, vfsOptions=%d, freq=%d, passno=%d",
308+
partuuid, entry.Target, entry.Source, entry.FsType, entry.Options, entry.FsOptions, entry.VfsOptions, entry.Freq, entry.PassNo)
309+
}
310+
311+
logger.Log.Debugf("Resolved base image verity metadata:")
312+
for _, v := range baseImageVerityMetadata {
313+
logger.Log.Debugf(" name=%s, rootHash=%s", v.name, v.rootHash)
314+
logger.Log.Debugf(" dataPartition: idType=%s, id=%s", v.dataDeviceMountIdType, v.dataPartUuid)
315+
logger.Log.Debugf(" hashPartition: idType=%s, id=%s", v.hashDeviceMountIdType, v.hashPartUuid)
316+
logger.Log.Debugf(" corruptionOption=%s, hashSignaturePath=%s", v.corruptionOption, v.hashSignaturePath)
317+
}
318+
319+
logger.Log.Debugf("OSRelease=%s", osRelease)
320+
321+
outputImageBase := strings.TrimSuffix(filepath.Base(outputImageFile), filepath.Ext(outputImageFile))
322+
323+
imageUuid, imageUuidStr, err := createUuid()
324+
if err != nil {
325+
return err
326+
}
327+
328+
// ToDo: ABOVE are preparing COSI image converting.
329+
//
285330
partitionsToMountpoints := make(map[imagecustomizerapi.InjectFilePartition]string)
286331
var mountedPartitions []*safemount.Mount
287332

@@ -323,12 +368,63 @@ func InjectFiles(buildDir string, baseConfigPath string, inputImageFile string,
323368
return err
324369
}
325370

326-
err = convertImageFile(rawImageFile, outputImageFile, detectedImageFormat)
327-
if err != nil {
328-
return fmt.Errorf("failed to convert customized raw image to output format:\n%w", err)
371+
if detectedImageFormat == imagecustomizerapi.ImageFormatTypeCosi {
372+
err := convertToCosiWhenInject(buildDirAbs, rawImageFile, outputImageBase, imageUuid, imageUuidStr, outputImageFile,
373+
baseImageVerityMetadata, partUuidToFstabEntry, osRelease)
374+
if err != nil {
375+
return err
376+
}
377+
} else {
378+
err = convertImageFile(rawImageFile, outputImageFile, detectedImageFormat)
379+
if err != nil {
380+
return fmt.Errorf("failed to convert customized raw image to output format:\n%w", err)
381+
}
329382
}
330383

331384
logger.Log.Infof("Success!")
332385

333386
return nil
334387
}
388+
389+
func convertToCosiWhenInject(buildDirAbs string, rawImageFile string, outputImageBase string,
390+
imageUuid [UuidSize]byte, imageUuidStr string, outputImageFile string, baseImageVerityMetadata []verityDeviceMetadata,
391+
partUuidToFstabEntry map[string]diskutils.FstabEntry, osRelease string,
392+
) error {
393+
logger.Log.Infof("Extracting partition files")
394+
outputDir := filepath.Join(buildDirAbs, "cosiimages")
395+
err := os.MkdirAll(outputDir, os.ModePerm)
396+
if err != nil {
397+
return fmt.Errorf("failed to create folder %s:\n%w", outputDir, err)
398+
}
399+
defer os.Remove(outputDir)
400+
401+
imageLoopback, err := safeloopback.NewLoopback(rawImageFile)
402+
if err != nil {
403+
return err
404+
}
405+
defer imageLoopback.Close()
406+
407+
partitionMetadataOutput, err := extractPartitions(imageLoopback.DevicePath(), outputDir, outputImageBase,
408+
"raw-zst", imageUuid)
409+
if err != nil {
410+
return err
411+
}
412+
for _, partition := range partitionMetadataOutput {
413+
defer os.Remove(path.Join(outputDir, partition.PartitionFilename))
414+
}
415+
416+
err = buildCosiFile(outputDir, outputImageFile, partitionMetadataOutput, baseImageVerityMetadata,
417+
partUuidToFstabEntry, imageUuidStr, osRelease)
418+
if err != nil {
419+
return fmt.Errorf("failed to build COSI file:\n%w", err)
420+
}
421+
422+
logger.Log.Infof("Successfully converted to COSI: %s", outputImageFile)
423+
424+
err = imageLoopback.CleanClose()
425+
if err != nil {
426+
return err
427+
}
428+
429+
return nil
430+
}

toolkit/tools/pkg/imagecustomizerlib/customizepartitionsuuids.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func fixPartitionUuidsInFstabFile(partitions []diskutils.PartitionInfo, newUuids
174174
// Find the partition.
175175
// Note: The 'partitions' list was collected before all the changes were made. So, the fstab entries will still
176176
// match the values in the `partitions` list.
177-
mountIdType, _, partitionIndex, err := findSourcePartition(fstabEntry.Source, partitions, buildDir)
177+
mountIdType, _, partitionIndex, _, err := findSourcePartition(fstabEntry.Source, partitions, buildDir)
178178
if err != nil {
179179
return err
180180
}

toolkit/tools/pkg/imagecustomizerlib/customizeverity.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"path/filepath"
99
"slices"
10+
"strings"
1011

1112
"github.com/microsoft/azurelinux/toolkit/tools/imagecustomizerapi"
1213
"github.com/microsoft/azurelinux/toolkit/tools/imagegen/diskutils"
@@ -413,3 +414,30 @@ func findIdentifiedPartition(partitions []diskutils.PartitionInfo, ref imagecust
413414
}
414415
return partition, nil
415416
}
417+
418+
func ParseSystemdVerityOptions(options string) (imagecustomizerapi.CorruptionOption, error) {
419+
corruptionOption := imagecustomizerapi.CorruptionOptionIoError
420+
421+
optionValues := strings.Split(options, ",")
422+
for _, option := range optionValues {
423+
switch option {
424+
case "":
425+
// Ignore empty string.
426+
427+
case "ignore-corruption":
428+
corruptionOption = imagecustomizerapi.CorruptionOptionIgnore
429+
430+
case "panic-on-corruption":
431+
corruptionOption = imagecustomizerapi.CorruptionOptionPanic
432+
433+
case "restart-on-corruption":
434+
corruptionOption = imagecustomizerapi.CorruptionOptionRestart
435+
436+
default:
437+
// ToDo: Ignore unknown options like "root-hash-signature=/boot/root.hash.sig"
438+
logger.Log.Debugf("Ignoring unknown verity option: %s", option)
439+
}
440+
}
441+
442+
return corruptionOption, nil
443+
}

toolkit/tools/pkg/imagecustomizerlib/imageutils.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ func connectToExistingImageHelper(imageConnection *ImageConnection, imageFilePat
5151
return nil, fmt.Errorf("failed to find rootfs partition:\n%w", err)
5252
}
5353

54-
fstabEntries, err := readFstabEntriesFromRootfs(rootfsPartition, partitions, buildDir)
54+
fstabEntries, _, err := readFstabEntriesFromRootfs(rootfsPartition, partitions, buildDir)
5555
if err != nil {
5656
return nil, fmt.Errorf("failed to read fstab entries from rootfs partition:\n%w", err)
5757
}
5858

59-
mountPoints, partUuidToFstabEntry, err := fstabEntriesToMountPoints(fstabEntries, partitions, buildDir)
59+
mountPoints, partUuidToFstabEntry, _, err := fstabEntriesToMountPoints(fstabEntries, partitions, buildDir)
6060
if err != nil {
6161
return nil, fmt.Errorf("failed to find mount info for fstab file entries:\n%w", err)
6262
}
@@ -245,7 +245,7 @@ func createImageBoilerplate(targetOs targetos.TargetOs, imageConnection *ImageCo
245245
return nil, "", err
246246
}
247247

248-
mountPoints, _, err := fstabEntriesToMountPoints(fstabEntries, diskPartitions, buildDir)
248+
mountPoints, _, _, err := fstabEntriesToMountPoints(fstabEntries, diskPartitions, buildDir)
249249
if err != nil {
250250
return nil, "", fmt.Errorf("failed to find mount info for fstab file entries:\n%w", err)
251251
}

0 commit comments

Comments
 (0)