Skip to content

Commit e18be06

Browse files
committed
pkg/architecture: Define core architecture types and constants
Introduce the architecture package that represents the core of the Toolbx cross-architecture support, which is based on user-mode emulation using QEMU and binfmt_misc. The Architecture struct collects all per-architecture data (ELF magic/mask, OCI and binfmt naming, aliases, binfmt registration parameters) into a single map. Architectures present in the supportedArchitectures map represent the set of supported architectures within Toolbx. Define architecture ID constants NotSpecified, Aarch64, Ppc64le, and X86_64, along with their supportedArchitectures entries. Add core query functions: - ParseArgArchValue() for resolving user-supplied architecture strings - GetArchNameBinfmt() and GetArchNameOCI() for name lookups (one architecture can have multiple valid names [1]) - HasContainerNativeArch() for comparing against the host - ImageReferenceGetArchFromTag() for extracting architecture from image tag suffixes like "42-aarch64" for architecture detection Expose the HostArchID package variable, which is set in the init() function, so the variable can be accessed in the early init() state from every inheritor that utilizes the architecture package (HostArchID serves as a default value for initContainer --arch flag), and the Config struct for preserving the architecture ID and the QEMU emulator path, through the call chain. [1] https://itsfoss.com/arm-aarch64-x86_64/ containers#1782 Signed-off-by: Dalibor Kricka <dalidalk@seznam.cz>
1 parent 4afa672 commit e18be06

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright © 2019 – 2026 Red Hat Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package architecture
18+
19+
import (
20+
"fmt"
21+
"runtime"
22+
"strings"
23+
24+
"github.com/containers/toolbox/pkg/utils"
25+
"github.com/sirupsen/logrus"
26+
)
27+
28+
type Architecture struct {
29+
ID int
30+
NameBinfmt string
31+
NameOCI string
32+
Aliases []string
33+
ELFMagic []byte
34+
ELFMask []byte
35+
36+
BinfmtFlags string
37+
BinfmtName string
38+
BinfmtMagicType string
39+
BinfmtOffset string
40+
}
41+
42+
type Config struct {
43+
ID int
44+
QemuEmulatorPath string
45+
}
46+
47+
const (
48+
NotSpecified = iota
49+
Aarch64
50+
Ppc64le
51+
X86_64
52+
)
53+
54+
var supportedArchitectures = map[int]Architecture{
55+
Aarch64: {
56+
ID: Aarch64,
57+
NameBinfmt: "aarch64",
58+
NameOCI: "arm64",
59+
Aliases: []string{"aarch64", "arm64"},
60+
ELFMagic: []byte{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb7, 0x00},
61+
ELFMask: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff},
62+
},
63+
Ppc64le: {
64+
ID: Ppc64le,
65+
NameBinfmt: "ppc64le",
66+
NameOCI: "ppc64le",
67+
Aliases: []string{"ppc64le"},
68+
ELFMagic: []byte{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x15, 0x00},
69+
ELFMask: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0x00},
70+
},
71+
X86_64: {
72+
ID: X86_64,
73+
NameBinfmt: "x86_64",
74+
NameOCI: "amd64",
75+
Aliases: []string{"x86_64", "amd64"},
76+
ELFMagic: []byte{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00},
77+
ELFMask: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff},
78+
},
79+
}
80+
81+
var (
82+
HostArchID int
83+
supportedArgArchValues map[string]int
84+
)
85+
86+
func init() {
87+
HostArchID, _ = ParseArgArchValue(runtime.GOARCH)
88+
89+
supportedArgArchValues = make(map[string]int)
90+
for archID, arch := range supportedArchitectures {
91+
for _, alias := range arch.Aliases {
92+
supportedArgArchValues[alias] = archID
93+
}
94+
}
95+
}
96+
97+
func GetArchConfigDefault() Config {
98+
return Config{
99+
ID: HostArchID,
100+
QemuEmulatorPath: "",
101+
}
102+
}
103+
104+
func getArchitecture(archID int) (Architecture, bool) {
105+
arch, exists := supportedArchitectures[archID]
106+
return arch, exists
107+
}
108+
109+
func getArchNameBinfmt(arch int) string {
110+
if arch == NotSpecified {
111+
logrus.Warnf("Getting arch name for not specified architecture")
112+
return "arch_not_specified"
113+
}
114+
if archObj, exists := supportedArchitectures[arch]; exists {
115+
return archObj.NameBinfmt
116+
}
117+
return ""
118+
}
119+
120+
func GetArchNameOCI(arch int) string {
121+
if arch == NotSpecified {
122+
logrus.Warnf("Getting arch name for not specified architecture")
123+
return "arch_not_specified"
124+
}
125+
if archObj, exists := supportedArchitectures[arch]; exists {
126+
return archObj.NameOCI
127+
}
128+
return ""
129+
}
130+
131+
func HasContainerNativeArch(archID int) bool {
132+
return archID == HostArchID
133+
}
134+
135+
func ImageReferenceGetArchFromTag(image string) int {
136+
tag := utils.ImageReferenceGetTag(image)
137+
138+
if tag == "" {
139+
return NotSpecified
140+
}
141+
142+
i := strings.LastIndexByte(tag, '-')
143+
if i == -1 {
144+
return NotSpecified
145+
}
146+
147+
archInTag := tag[i+1:]
148+
149+
for archID, arch := range supportedArchitectures {
150+
if arch.NameBinfmt == archInTag || arch.NameOCI == archInTag {
151+
return archID
152+
}
153+
}
154+
155+
return NotSpecified
156+
}
157+
158+
func ParseArgArchValue(value string) (int, error) {
159+
archID, exists := supportedArgArchValues[value]
160+
if !exists {
161+
return NotSpecified, fmt.Errorf("architecture '%s' is not supported by Toolbx", value)
162+
}
163+
164+
return archID, nil
165+
}

0 commit comments

Comments
 (0)