Skip to content

Commit

Permalink
Add boot rank to OSImage interface.
Browse files Browse the repository at this point in the history
The rank represents the boot order of the images. The higher the
rank, the prior the image shows in the boot menu.

We set the BLS block to a higher default rank and add a command line flag
"BLS_BOOT_RANK" to control the boot order.

Signed-off-by: Terry Tang <[email protected]>
  • Loading branch information
Terry Tang authored and probot-auto-merge[bot] committed Jul 24, 2021
1 parent a2120b5 commit 637617c
Show file tree
Hide file tree
Showing 27 changed files with 650 additions and 253 deletions.
11 changes: 11 additions & 0 deletions pkg/boot/bls/bls.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"os"
"path/filepath"
"sort"
"strconv"
"strings"

"github.com/u-root/u-root/pkg/boot"
Expand All @@ -27,6 +28,9 @@ import (

const (
blsEntriesDir = "loader/entries"
// Set a higher default rank for BLS. It should be booted prior to the
// other local images.
blsDefaultRank = 1
)

func cutConf(s string) string {
Expand Down Expand Up @@ -195,6 +199,13 @@ func parseLinuxImage(vals map[string]string, fsRoot string) (boot.OSImage, error
// If both title and version were empty, so will this.
linux.Name = strings.Join(name, " ")
linux.Cmdline = strings.Join(cmdlines, " ")
linux.BootRank = blsDefaultRank
if val, exist := os.LookupEnv("BLS_BOOT_RANK"); exist {
if rank, err := strconv.Atoi(val); err == nil {
linux.BootRank = rank
}
}

return linux, nil
}

Expand Down
60 changes: 47 additions & 13 deletions pkg/boot/bls/bls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ package bls

import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"testing"

Expand All @@ -27,6 +29,28 @@ var blsEntries = []struct {
},
}

// Enable this temporarily to generate new configs. Double-check them by hand.
func DISABLEDTestGenerateConfigs(t *testing.T) {
tests, err := filepath.Glob("testdata/*.json")
if err != nil {
t.Error("Failed to find test config files:", err)
}

for _, test := range tests {
configPath := strings.TrimRight(test, ".json")
t.Run(configPath, func(t *testing.T) {
imgs, err := ScanBLSEntries(ulogtest.Logger{t}, configPath)
if err != nil {
t.Fatalf("Failed to parse %s: %v", test, err)
}

if err := boottest.ToJSONFile(imgs, test); err != nil {
t.Errorf("failed to generate file: %v", err)
}
})
}
}

func TestParseBLSEntries(t *testing.T) {
fsRoot := "./testdata/madeup"
dir := filepath.Join(fsRoot, "loader/entries")
Expand Down Expand Up @@ -78,24 +102,34 @@ func TestScanBLSEntries(t *testing.T) {
}
}

// Enable this temporarily to generate new configs. Double-check them by hand.
func DISABLEDTestGenerateConfigs(t *testing.T) {
tests, err := filepath.Glob("testdata/*.json")
if err != nil {
t.Error("Failed to find test config files:", err)
}
func TestSetBLSRank(t *testing.T) {
fsRoot := "./testdata/madeup"
dir := filepath.Join(fsRoot, "loader/entries")
testRank := 2
originRank := os.Getenv("BLS_BOOT_RANK")
os.Setenv("BLS_BOOT_RANK", strconv.Itoa(testRank))

for _, test := range tests {
configPath := strings.TrimRight(test, ".json")
t.Run(configPath, func(t *testing.T) {
imgs, err := ScanBLSEntries(ulogtest.Logger{t}, configPath)
for _, tt := range blsEntries {
t.Run(tt.entry, func(t *testing.T) {
image, err := parseBLSEntry(filepath.Join(dir, tt.entry), fsRoot)
if err != nil {
t.Fatalf("Failed to parse %s: %v", test, err)
if tt.err == "" {
t.Fatalf("Got error %v", err)
}
if !strings.Contains(err.Error(), tt.err) {
t.Fatalf("Got error %v, expected error to contain %s", err, tt.err)
}
return
}
if tt.err != "" {
t.Fatalf("Expected error %s, got no error", tt.err)
}

if err := boottest.ToJSONFile(imgs, test); err != nil {
t.Errorf("failed to generate file: %v", err)
if image.Rank() != testRank {
t.Errorf("Expected rank %d, got %d", testRank, image.Rank())
}
})
}

os.Setenv("BLS_BOOT_RANK", originRank)
}
6 changes: 4 additions & 2 deletions pkg/boot/bls/testdata/fedora_32.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"kernel": {
"name": "testdata/fedora_32/de8380606ce44a2dabad127eb049acbe/5_6_6_300_fc32_x86_64/linux"
},
"name": "Fedora 32 (Server Edition) 5.6.6-300.fc32.x86_64"
"name": "Fedora 32 (Server Edition) 5.6.6-300.fc32.x86_64",
"rank": "1"
},
{
"cmdline": "BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.6.6-300.fc32.x86_64 root=UUID=b0b50629-c323-40de-9b01-05632be6dbd4 ro resume=UUID=abf0a2b5-f8db-411b-b534-1a431c63fbc0 console=ttyS0 rd.auto=1",
Expand All @@ -19,6 +20,7 @@
"kernel": {
"name": "testdata/fedora_32/de8380606ce44a2dabad127eb049acbe/0_rescue/linux"
},
"name": "Fedora 32 (Server Edition) - Rescue Image 5.6.6-300.fc32.x86_64"
"name": "Fedora 32 (Server Edition) - Rescue Image 5.6.6-300.fc32.x86_64",
"rank": "1"
}
]
3 changes: 2 additions & 1 deletion pkg/boot/bls/testdata/madeup.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"kernel": {
"name": "testdata/madeup/loader/fakefile"
},
"name": "Fedora 19 (Rawhide) 3.8.0-2.fc19.x86_64"
"name": "Fedora 19 (Rawhide) 3.8.0-2.fc19.x86_64",
"rank": "1"
}
]
5 changes: 5 additions & 0 deletions pkg/boot/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ type OSImage interface {
// Label is intended for boot menus.
Label() string

// Rank the priority of the images for boot menus.
//
// The larger the number, the prior the image shows in the menu.
Rank() int

// Edit the kernel command line if possible. Must be called before
// Load.
Edit(func(cmdline string) string)
Expand Down
3 changes: 3 additions & 0 deletions pkg/boot/boottest/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"io/ioutil"
"net/url"
"os"
"strconv"
"strings"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -131,6 +132,7 @@ func LinuxImageToJSON(li *boot.LinuxImage) map[string]interface{} {
m["image_type"] = "linux"
m["name"] = li.Name
m["cmdline"] = li.Cmdline
m["rank"] = strconv.Itoa(li.BootRank)
if li.Kernel != nil {
m["kernel"] = module(li.Kernel)
}
Expand All @@ -149,6 +151,7 @@ func MultibootImageToJSON(mi *boot.MultibootImage) map[string]interface{} {
m["image_type"] = "multiboot"
m["name"] = mi.Name
m["cmdline"] = mi.Cmdline
m["rank"] = strconv.Itoa(mi.BootRank)
if mi.Kernel != nil {
m["kernel"] = module(mi.Kernel)
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/boot/fit/fit.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type Image struct {
ConfigOverride string
// SkipInitRAMFS skips the search for an ramdisk entry in the config
SkipInitRAMFS bool
// BootRank ranks the priority of the images in boot menu
BootRank int
}

var _ = boot.OSImage(&Image{})
Expand Down Expand Up @@ -90,6 +92,11 @@ func (i *Image) Label() string {
return fmt.Sprintf("%s (kernel: %s)", i.name, i.Kernel)
}

// Rank returns an Image Rank.
func (i *Image) Rank() int {
return i.BootRank
}

// Edit edits the Image cmdline using a func.
func (i *Image) Edit(f func(s string) string) {
i.Cmdline = f(i.Cmdline)
Expand Down
9 changes: 9 additions & 0 deletions pkg/boot/fit/fit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,12 @@ func TestLabel(t *testing.T) {
t.Fatalf("Expected Image label to contain name %s, got %s", n, l)
}
}

func TestRank(t *testing.T) {
testRank := 2
img := &Image{BootRank: testRank}
l := img.Rank()
if l != testRank {
t.Fatalf("Expected Image rank %d, got %d", testRank, l)
}
}
12 changes: 8 additions & 4 deletions pkg/boot/grub/testdata_new/CentOS_7_x86_64_DVD_1810.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810/images/pxeboot/vmlinuz"
},
"name": "Test this media \u0026 install CentOS 7"
"name": "Test this media \u0026 install CentOS 7",
"rank": "0"
},
{
"cmdline": "inst.stage2=hd:LABEL=CentOS\\x207\\x20x86_64 quiet",
Expand All @@ -19,7 +20,8 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810/images/pxeboot/vmlinuz"
},
"name": "Install CentOS 7"
"name": "Install CentOS 7",
"rank": "0"
},
{
"cmdline": "inst.stage2=hd:LABEL=CentOS\\x207\\x20x86_64 xdriver=vesa nomodeset quiet",
Expand All @@ -30,7 +32,8 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810/images/pxeboot/vmlinuz"
},
"name": "Install CentOS 7 in basic graphics mode"
"name": "Install CentOS 7 in basic graphics mode",
"rank": "0"
},
{
"cmdline": "inst.stage2=hd:LABEL=CentOS\\x207\\x20x86_64 rescue quiet",
Expand All @@ -41,6 +44,7 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810/images/pxeboot/vmlinuz"
},
"name": "Rescue a CentOS system"
"name": "Rescue a CentOS system",
"rank": "0"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810_efi_install_sda2/vmlinuz-3.10.0-957.el7.x86_64"
},
"name": "CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)"
"name": "CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)",
"rank": "0"
},
{
"cmdline": "root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap console=ttyS0,115200,8n1",
Expand All @@ -19,6 +20,7 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810_efi_install_sda2/vmlinuz-0-rescue-95c8409b55ce443baf15cad9e750348d"
},
"name": "CentOS Linux (0-rescue-95c8409b55ce443baf15cad9e750348d) 7 (Core)"
"name": "CentOS Linux (0-rescue-95c8409b55ce443baf15cad9e750348d) 7 (Core)",
"rank": "0"
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810_legacy_install_sda1/vmlinuz-3.10.0-957.el7.x86_64"
},
"name": "CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)"
"name": "CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)",
"rank": "0"
},
{
"cmdline": "root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap console=ttyS0,115200,8n1",
Expand All @@ -19,6 +20,7 @@
"kernel": {
"url": "file:///testdata_new/CentOS_7_x86_64_DVD_1810_legacy_install_sda1/vmlinuz-0-rescue-d2794e72bf4d44508b9ba5d447dd14ff"
},
"name": "CentOS Linux (0-rescue-d2794e72bf4d44508b9ba5d447dd14ff) 7 (Core)"
"name": "CentOS Linux (0-rescue-d2794e72bf4d44508b9ba5d447dd14ff) 7 (Core)",
"rank": "0"
}
]
]
9 changes: 6 additions & 3 deletions pkg/boot/grub/testdata_new/debian_10_4_installed.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"kernel": {
"url": "file:///testdata_new/debian_10_4_installed/boot/vmlinuz-4.19.0-9-amd64"
},
"name": "Debian GNU/Linux"
"name": "Debian GNU/Linux",
"rank": "0"
},
{
"cmdline": "root=UUID=39ec20e2-83f5-44ce-8671-f31ce0856377 ro console=ttyS0 quiet",
Expand All @@ -19,7 +20,8 @@
"kernel": {
"url": "file:///testdata_new/debian_10_4_installed/boot/vmlinuz-4.19.0-9-amd64"
},
"name": "Debian GNU/Linux, with Linux 4.19.0-9-amd64"
"name": "Debian GNU/Linux, with Linux 4.19.0-9-amd64",
"rank": "0"
},
{
"cmdline": "root=UUID=39ec20e2-83f5-44ce-8671-f31ce0856377 ro single console=ttyS0",
Expand All @@ -30,6 +32,7 @@
"kernel": {
"url": "file:///testdata_new/debian_10_4_installed/boot/vmlinuz-4.19.0-9-amd64"
},
"name": "Debian GNU/Linux, with Linux 4.19.0-9-amd64 (recovery mode)"
"name": "Debian GNU/Linux, with Linux 4.19.0-9-amd64 (recovery mode)",
"rank": "0"
}
]
Loading

0 comments on commit 637617c

Please sign in to comment.