Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.16-rc2 66 lines 2.0 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only OR MIT 2/* Copyright (c) 2024 Imagination Technologies Ltd. */ 3 4#include "pvr_device.h" 5#include "pvr_fw.h" 6 7#include <drm/drm_device.h> 8#include <drm/drm_print.h> 9 10#include <linux/elf.h> 11#include <linux/string.h> 12#include <linux/types.h> 13 14/** 15 * pvr_fw_process_elf_command_stream() - Process ELF firmware image and populate 16 * firmware sections 17 * @pvr_dev: Device pointer. 18 * @fw: Pointer to firmware image. 19 * @fw_code_ptr: Pointer to FW code section. 20 * @fw_data_ptr: Pointer to FW data section. 21 * @fw_core_code_ptr: Pointer to FW coremem code section. 22 * @fw_core_data_ptr: Pointer to FW coremem data section. 23 * 24 * Returns : 25 * * 0 on success, or 26 * * -EINVAL on any error in ELF command stream. 27 */ 28int 29pvr_fw_process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, 30 u8 *fw_code_ptr, u8 *fw_data_ptr, 31 u8 *fw_core_code_ptr, u8 *fw_core_data_ptr) 32{ 33 struct elf32_hdr *header = (struct elf32_hdr *)fw; 34 struct elf32_phdr *program_header = (struct elf32_phdr *)(fw + header->e_phoff); 35 struct drm_device *drm_dev = from_pvr_device(pvr_dev); 36 int err; 37 38 for (u32 entry = 0; entry < header->e_phnum; entry++, program_header++) { 39 void *write_addr; 40 41 /* Only consider loadable entries in the ELF segment table */ 42 if (program_header->p_type != PT_LOAD) 43 continue; 44 45 err = pvr_fw_find_mmu_segment(pvr_dev, program_header->p_vaddr, 46 program_header->p_memsz, fw_code_ptr, fw_data_ptr, 47 fw_core_code_ptr, fw_core_data_ptr, &write_addr); 48 if (err) { 49 drm_err(drm_dev, 50 "Addr 0x%x (size: %d) not found in any firmware segment", 51 program_header->p_vaddr, program_header->p_memsz); 52 return err; 53 } 54 55 /* Write to FW allocation only if available */ 56 if (write_addr) { 57 memcpy(write_addr, fw + program_header->p_offset, 58 program_header->p_filesz); 59 60 memset((u8 *)write_addr + program_header->p_filesz, 0, 61 program_header->p_memsz - program_header->p_filesz); 62 } 63 } 64 65 return 0; 66}