blob: e5632b93aa8a38a2c5b103e4ea3338910b9a277a [file] [log] [blame]
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tools
import (
"fmt"
"log"
"strconv"
"cos.googlesource.com/cos/tools.git/src/pkg/tools/partutil"
)
// ExtendOEMPartition moves stateful partition towards the end of the disk
// Then move OEM partition to the original place of the stateful partition
// Finally resize the OEM partition to 1 sector before the new stateful partition
// OEMSize can be the number of sectors (without unit) or size like "3G", "100M", "10000K" or "99999B"
func ExtendOEMPartition(disk string, statePartNum, oemPartNum int, oemSize string) error {
if len(disk) <= 0 || statePartNum <= 0 || oemPartNum <= 0 || len(oemSize) <= 0 {
return fmt.Errorf("empty or non-positive input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q",
disk, statePartNum, oemPartNum, oemSize)
}
// read new size of OEM partition.
newOEMSizeBytes, err := partutil.ConvertSizeToBytes(oemSize)
if err != nil {
return fmt.Errorf("error in reading new OEM size, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, statePartNum, oemPartNum, oemSize, err)
}
// read original size of OEM partition.
oldOEMSize, err := partutil.ReadPartitionSize(disk, oemPartNum)
if err != nil {
return fmt.Errorf("error in reading old OEM size, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, statePartNum, oemPartNum, oemSize, err)
}
oldOEMSizeBytes := oldOEMSize << 9 // change unit to bytes.
if newOEMSizeBytes <= oldOEMSizeBytes {
log.Printf("\n!!!!!!!WARNING!!!!!!!\n"+
"oemSize: %d bytes is not larger than the original OEM partition size: %d bytes, "+
"nothing is done\n "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q",
newOEMSizeBytes, oldOEMSizeBytes, disk, statePartNum, oemPartNum, oemSize)
return nil
}
// print the old partition table.
table, err := partutil.ReadPartitionTable(disk)
if err != nil {
return fmt.Errorf("cannot read old partition table of %q, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, disk, statePartNum, oemPartNum, oemSize, err)
}
log.Printf("\nOld partition table:\n%s\n", table)
// record the original start sector of the stateful partition.
oldStateStartSector, err := partutil.ReadPartitionStart(disk, statePartNum)
if err != nil {
return fmt.Errorf("cannot read old stateful partition start, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, statePartNum, oemPartNum, oemSize, err)
}
// move the stateful partition.
if err := partutil.MovePartition(disk, statePartNum, "+"+oemSize); err != nil {
return fmt.Errorf("error in moving stateful partition, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, statePartNum, oemPartNum, oemSize, err)
}
// record the new start sector of the stateful partition.
newStateStartSector, err := partutil.ReadPartitionStart(disk, statePartNum)
if err != nil {
return fmt.Errorf("cannot read new stateful partition start, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, statePartNum, oemPartNum, oemSize, err)
}
// move OEM partition to the original start sector of the stateful partition.
if err := partutil.MovePartition(disk, oemPartNum, strconv.FormatUint(oldStateStartSector, 10)); err != nil {
return fmt.Errorf("error in moving OEM partition, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, statePartNum, oemPartNum, oemSize, err)
}
// extend the OEM partition.
if err = partutil.ExtendPartition(disk, oemPartNum, newStateStartSector-1); err != nil {
return fmt.Errorf("error in extending OEM partition, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, statePartNum, oemPartNum, oemSize, err)
}
// print the new partition table.
table, err = partutil.ReadPartitionTable(disk)
if err != nil {
return fmt.Errorf("cannot read new partition table of %q, "+
"input: disk=%q, statePartNum=%d, oemPartNum=%d, oemSize=%q, "+
"error msg: (%v)", disk, disk, statePartNum, oemPartNum, oemSize, err)
}
log.Printf("\nCompleted extending OEM partition\n\n New partition table:\n%s\n", table)
return nil
}