/* SPDX-License-Identifier: GPL-2.0+ */ /* * load.c - pull the payload into RAM. semihosting is the qemu path, * flash and block devices follow the same shape once they exist. * * Copyright (C) 2026 Bradley Morgan */ #include #include #include #include #include /* * load fname into mem_base. the header decides the real placement, so * we read the whole file first and let tb_image_setup place it. */ int tb_load_semihosting(const char *fname, uintptr_t load_addr, uintptr_t mem_base, uint32 mem_size, struct tb_image *img) { struct Image_header *ih = (struct Image_header *)load_addr; long fd; long len; long ret; fd = smh_open(fname, MODE_READ | MODE_BINARY); if (fd < 0) return fd; len = smh_flen(fd); if (len < 0) { smh_close(fd); return len; } if ((uint32)len > mem_size) { smh_close(fd); return -2; } /* header first so placement is known before the big copy */ ret = smh_read(fd, (void *)load_addr, sizeof(*ih)); if (ret != sizeof(*ih)) { smh_close(fd); return -3; } if (tb_image_setup(load_addr, mem_base, mem_size, img)) { smh_close(fd); return -4; } if (img->load != load_addr) { /* the image wants to sit elsewhere, copy it there */ memmove((void *)img->load, (void *)load_addr, sizeof(*ih)); } ret = smh_read(fd, (void *)(img->load + sizeof(*ih)), len - sizeof(*ih)); if (ret != len - sizeof(*ih)) { smh_close(fd); return -5; } smh_close(fd); return 0; }