1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun #include <linux/efi_embedded_fw.h> 4*4882a593Smuzhiyun #include <linux/property.h> 5*4882a593Smuzhiyun #include <linux/security.h> 6*4882a593Smuzhiyun #include <linux/vmalloc.h> 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun #include "fallback.h" 9*4882a593Smuzhiyun #include "firmware.h" 10*4882a593Smuzhiyun firmware_fallback_platform(struct fw_priv * fw_priv)11*4882a593Smuzhiyunint firmware_fallback_platform(struct fw_priv *fw_priv) 12*4882a593Smuzhiyun { 13*4882a593Smuzhiyun const u8 *data; 14*4882a593Smuzhiyun size_t size; 15*4882a593Smuzhiyun int rc; 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun if (!(fw_priv->opt_flags & FW_OPT_FALLBACK_PLATFORM)) 18*4882a593Smuzhiyun return -ENOENT; 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun rc = security_kernel_load_data(LOADING_FIRMWARE, true); 21*4882a593Smuzhiyun if (rc) 22*4882a593Smuzhiyun return rc; 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun rc = efi_get_embedded_fw(fw_priv->fw_name, &data, &size); 25*4882a593Smuzhiyun if (rc) 26*4882a593Smuzhiyun return rc; /* rc == -ENOENT when the fw was not found */ 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun if (fw_priv->data && size > fw_priv->allocated_size) 29*4882a593Smuzhiyun return -ENOMEM; 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun rc = security_kernel_post_load_data((u8 *)data, size, LOADING_FIRMWARE, 32*4882a593Smuzhiyun "platform"); 33*4882a593Smuzhiyun if (rc) 34*4882a593Smuzhiyun return rc; 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun if (!fw_priv->data) 37*4882a593Smuzhiyun fw_priv->data = vmalloc(size); 38*4882a593Smuzhiyun if (!fw_priv->data) 39*4882a593Smuzhiyun return -ENOMEM; 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun memcpy(fw_priv->data, data, size); 42*4882a593Smuzhiyun fw_priv->size = size; 43*4882a593Smuzhiyun fw_state_done(fw_priv); 44*4882a593Smuzhiyun return 0; 45*4882a593Smuzhiyun } 46