RPi-Distro / pi-gen

Tool used to create the official Raspberry Pi OS images
BSD 3-Clause "New" or "Revised" License
2.65k stars 1.65k forks source link

./build-docker.sh error "setarch: failed to set personality to linux32: Invalid argument" #764

Closed naturaverl closed 1 month ago

naturaverl commented 7 months ago

Hi, first time pi-gen user here. I'm on a M1 mac, trying to use pi-gen to build a standard image (nothing's been added in by me, yet)

I'm trying to follow the README to learn how to use pi-gen, and understand that I can use Docker for pi-gen to have a debian environment to run from. On my Mac mini M1 system, I've simply cloned from pi-gen master branch, am using the build-docker.sh script, and the simplest of uses is failing for me. [EDIT] I've checked out the arm64 branch and that works better for me. The README didn't specifically mention needing to run the arm64 branch if your host is arm64.

studio-2:pi-gen jay$ echo IMG_NAME=\'raspios\' > config
studio-2:pi-gen jay$ ./build-docker.sh 
[+] Building 0.4s (8/8) FINISHED                                                                                                         docker:desktop-linux
 => [internal] load .dockerignore                                                                                                                        0.0s
 => => transferring context: 92B                                                                                                                         0.0s
 => [internal] load build definition from Dockerfile                                                                                                     0.0s
 => => transferring dockerfile: 542B                                                                                                                     0.0s
 => [internal] load metadata for docker.io/library/debian:bullseye                                                                                       0.3s
 => [1/3] FROM docker.io/library/debian:bullseye@sha256:26d72b71f88865377988af6f54da9aaa5bed201f39bcee13eb55737016660df2                                 0.0s
 => [internal] load build context                                                                                                                        0.0s
 => => transferring context: 10.87kB                                                                                                                     0.0s
 => CACHED [2/3] RUN apt-get -y update &&     apt-get -y install --no-install-recommends         git vim parted         quilt coreutils qemu-user-stati  0.0s
 => [3/3] COPY . /pi-gen/                                                                                                                                0.0s
 => exporting to image                                                                                                                                   0.0s
 => => exporting layers                                                                                                                                  0.0s
 => => writing image sha256:aba1ee87141ac3c050a7c4395f1af93dcd31d77d8a90321bd14dd2c7c0596b08                                                             0.0s
 => => naming to docker.io/library/pi-gen                                                                                                                0.0s

What's Next?
  1. Sign in to your Docker account → docker login
  2. View a summary of image vulnerabilities and recommendations → docker scout quickview
[19:51:53] Begin /pi-gen
[19:51:53] Begin /pi-gen/stage0
[19:51:53] Begin /pi-gen/stage0/prerun.sh
setarch: failed to set personality to linux32: Invalid argument
[19:51:53] End /pi-gen/stage0/prerun.sh
[19:51:53] Begin /pi-gen/stage0/00-configure-apt
[19:51:53] Begin /pi-gen/stage0/00-configure-apt/00-run.sh
install: target '/pi-gen/work/raspios/stage0/rootfs/etc/apt/' is not a directory: No such file or directory
XECDesign commented 7 months ago

first time pi-gen user here

Sorry it didn't all go as smoothly as it should've. I'm not familiar with Macs at all, so I'm not sure I'll be of much help here.

Do you need to build armhf images or arm64 images? If you don't need armhf images, you could try building from the 'arm64' branch and see if you have better luck.

Otherwise, do M1 macs support arm32 instructions natively or only aarch64? If it's only aarch64, then there's not much of a chance that this will work.

satmandu commented 1 month ago

Arm macs do not support arm32/armv7l/armv8l/armhf.

(Neither does the RPI5 unless it is booted into 4k page mode...)

hmeerlo commented 1 month ago

running into the same issue. I don't quite understand why the setarch linux32 is needed here?

satmandu commented 1 month ago

32-bit arm isn't like 32-bit x86_64. x86_64 processors support i686 instructions by default. 64-bit arm (aarch64/arm64) is different from 32-bit arm (armhf/armv7l/armv8l/etc...).

Only some 64-bit arm processors support both 32-bit arm and 64-bit arm instructions simultaneously, and even then only in certain modes.

Desktop arm macs are aarch64 only, and have never supported 32-bit arm. (iOS devices stopped supporting 32-bit arm years ago.)

Building the 32-bit arm rpi distribution requires running certain 32-bit arm apps during the build, so you need support for that architecture (armhf/armv7l/armv8l). In linux, you can emulate missing architecture support with some kernel-level emulation referred to as binfmt, as mentioned at https://github.com/RPi-Distro/pi-gen/tree/master#binfmt_misc . Generally, on top of having that support, when you try to run 32-bit software in linux on top of a 64-bit kernel, you can have that architecture switch supported by prefixing commands with the linux32 command.

macOS doesn't have that ability.

But maybe you can get around these issues by using some form of binfmt that might work on macs?

Does running this first as part of the build process help at all?

docker pull tonistiigi/binfmt
docker run --privileged --rm tonistiigi/binfmt --uninstall qemu-*
docker run --privileged --rm tonistiigi/binfmt --install all
XECDesign commented 1 month ago

To elaborate a bit on why setarch linux32 is used at all. Some applications use uname -m to determine the host machine architecture. When running a 64bit kernel, that gives you:

$ uname -m
aarch64

That can lead to incorrect assumptions when building a 32bit image. When you wrap that with setarch linux32, you get:

$ setarch linux32 uname -m
armv8l

However, in this case it sounds like setarch isn't the issue. You're just building on a machine that doesn't support the 32bit arm instructions.

hmeerlo commented 1 month ago

Thanks guys, things are clarified for me now!

XECDesign commented 1 month ago

I believe build.sh should be a bit clearer now if there are architecture or page size incompatibilities and README.md mentions the requirement of using different branches.