github.com/Microsoft/azure-vhd-utils@v0.0.0-20230613175315-7c30a3748a1b/vhdcore/footer/diskGeometry.go (about) 1 package footer 2 3 import ( 4 "fmt" 5 6 "github.com/Microsoft/azure-vhd-utils/vhdcore" 7 ) 8 9 // DiskGeometry represents the cylinder, heads and sectors (CHS) per track. 10 // 11 type DiskGeometry struct { 12 // Offset = 0, Size = 2 13 // Stored in big-endian format 14 Cylinder uint16 15 // Offset = 2, Size = 1 16 Heads byte 17 // Offset = 3, Size = 1 18 Sectors byte 19 } 20 21 // CreateNewDiskGeometry creates a new DiskGeometry from the given virtual 22 // size. CHS field values are calculated based on the total data sectors 23 // present in the disk image. 24 // 25 func CreateNewDiskGeometry(virtualSize int64) *DiskGeometry { 26 // Total data sectors present in the disk image 27 var totalSectors = virtualSize / vhdcore.VhdSectorLength 28 // Sectors per track on the disk 29 var sectorsPerTrack int64 30 // Number of heads present on the disk 31 var heads int32 32 // Cylinders * heads 33 var cylinderTimesHeads int64 34 35 // C * H * S 36 if totalSectors > 65535*16*255 { 37 totalSectors = 65535 * 16 * 255 38 } 39 40 if totalSectors >= 65535*16*63 { 41 sectorsPerTrack = 255 42 cylinderTimesHeads = totalSectors / sectorsPerTrack 43 heads = 16 44 45 return &DiskGeometry{ 46 Cylinder: uint16(cylinderTimesHeads / int64(heads)), 47 Heads: byte(heads), 48 Sectors: byte(sectorsPerTrack), 49 } 50 } 51 52 sectorsPerTrack = 17 53 cylinderTimesHeads = totalSectors / sectorsPerTrack 54 heads = int32((cylinderTimesHeads + 1023) / 1024) 55 56 if heads < 4 { 57 heads = 4 58 } 59 60 if cylinderTimesHeads >= int64(heads*1024) || heads > 16 { 61 sectorsPerTrack = 31 62 heads = 16 63 cylinderTimesHeads = totalSectors / sectorsPerTrack 64 } 65 66 if cylinderTimesHeads >= int64(heads*1024) { 67 sectorsPerTrack = 63 68 heads = 16 69 cylinderTimesHeads = totalSectors / sectorsPerTrack 70 } 71 72 return &DiskGeometry{ 73 Cylinder: uint16(cylinderTimesHeads / int64(heads)), 74 Heads: byte(heads), 75 Sectors: byte(sectorsPerTrack), 76 } 77 } 78 79 // CreateCopy creates a copy of this instance 80 // 81 func (d *DiskGeometry) CreateCopy() *DiskGeometry { 82 return &DiskGeometry{ 83 Cylinder: d.Cylinder, 84 Heads: d.Heads, 85 Sectors: d.Sectors, 86 } 87 } 88 89 // Equals returns true if this and other points to the same instance 90 // or if CHS fields of pointed instances are same 91 // 92 func (d *DiskGeometry) Equals(other *DiskGeometry) bool { 93 if other == nil { 94 return false 95 } 96 97 return other == d || *other == *d 98 } 99 100 // String returns the string representation of this range, this satisfies stringer interface. 101 // 102 func (d *DiskGeometry) String() string { 103 return fmt.Sprintf("Cylinder:%d Heads:%d Sectors:%d", d.Cylinder, d.Heads, d.Sectors) 104 }