| 718 | super().run() |
| 719 | |
| 720 | |
| 721 | def guess_arch(kernel_arg: Path) -> str: |
| 722 | # kernel_arg is either a path to the kernel build folder or a full kernel |
| 723 | # location. If it is a file, we need to strip off the basename so that we |
| 724 | # can easily navigate around with '..'. |
| 725 | if (kernel_dir := kernel_arg).is_file(): |
| 726 | kernel_dir = kernel_dir.parent |
| 727 | |
| 728 | # If kernel_location is the kernel build folder, vmlinux will be at |
| 729 | # <kernel_dir>/vmlinux |
| 730 | # |
| 731 | # If kernel_location is a full kernel location, it could either be: |
| 732 | # * <kernel_dir>/vmlinux (if the image is vmlinux) |
| 733 | # * <kernel_dir>/../../../vmlinux (if the image is in arch/*/boot/) |
| 734 | # |
| 735 | # Note: 'required=False' just to provide our own exception. |
| 736 | vmlinux_locations = ['vmlinux', '../../../vmlinux'] |
| 737 | if not (vmlinux := utils.find_first_file(kernel_dir, vmlinux_locations, required=False)): |
| 738 | msg = 'Architecture was not provided and vmlinux could not be found!' |
| 739 | raise RuntimeError(msg) |
| 740 | |
| 741 | if not (file := shutil.which('file')): |
| 742 | msg = "Architecture was not provided and 'file' is not installed!" |
| 743 | raise RuntimeError(msg) |
| 744 | |
| 745 | # Get output of file |
| 746 | file_out = subprocess.run( |
| 747 | [file, vmlinux], capture_output=True, check=True, text=True |
| 748 | ).stdout.strip() |
| 749 | |
| 750 | # Unfortunately, 'file' is not terribly precise when it comes to |
| 751 | # microarchitecture or architecture revisions. As such, there are certain |
| 752 | # strings that are just ambiguous so we bail out and let the user tell us |
| 753 | # exactly what architecture they were hoping to boot. |
| 754 | file_rosetta: dict[str, str] = { |
| 755 | 'ELF 32-bit LSB executable, ARM, EABI5': 'ambiguous', # could be any arm32 |
| 756 | 'ELF 64-bit LSB executable, ARM aarch64': 'arm64', |
| 757 | 'ELF 64-bit MSB executable, ARM aarch64': 'arm64be', |
| 758 | 'ELF 64-bit LSB pie executable, ARM aarch64': 'arm64', |
| 759 | 'ELF 64-bit MSB pie executable, ARM aarch64': 'arm64be', |
| 760 | 'ELF 64-bit LSB executable, LoongArch': 'loongarch', |
| 761 | 'ELF 32-bit MSB executable, Motorola m68k, 68020': 'm68k', |
| 762 | 'ELF 32-bit MSB executable, MIPS, MIPS32': 'mips', |
| 763 | 'ELF 32-bit LSB executable, MIPS, MIPS32': 'mipsel', |
| 764 | 'ELF 32-bit MSB executable, PowerPC': 'ambiguous', # could be ppc32 or ppc32_mac |
| 765 | 'ELF 64-bit MSB executable, 64-bit PowerPC or cisco 7500, Power ELF V1 ABI': 'ppc64', |
| 766 | 'ELF 64-bit MSB executable, 64-bit PowerPC or cisco 7500, OpenPOWER ELF V2 ABI': 'ppc64', |
| 767 | 'ELF 64-bit MSB pie executable, 64-bit PowerPC or cisco 7500, OpenPOWER ELF V2 ABI': 'ppc64', |
| 768 | 'ELF 64-bit LSB executable, 64-bit PowerPC or cisco 7500, OpenPOWER ELF V2 ABI': 'ppc64le', |
| 769 | 'ELF 64-bit LSB executable, UCB RISC-V': 'riscv', |
| 770 | 'ELF 64-bit MSB executable, IBM S/390': 's390', |
| 771 | 'ELF 64-bit MSB executable, SPARC V9': 'sparc64', |
| 772 | 'ELF 32-bit LSB executable, Intel 80386': 'x86', |
| 773 | 'ELF 64-bit LSB executable, x86-64': 'x86_64', |
| 774 | } # fmt: off |
| 775 | for string, value in file_rosetta.items(): |
| 776 | if string in file_out: |
| 777 | if value == 'ambiguous': |