mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-27 12:15:19 +01:00
7c0aa811ec
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
534 lines
15 KiB
C
534 lines
15 KiB
C
/*
|
|
* Copyright 2009 Jasmin Fazlic All rights reserved.
|
|
*
|
|
*
|
|
* Cleaned and merged by iNDi
|
|
*/
|
|
// UEFI adaptation by usr-sse2, then slice, dmazar
|
|
|
|
|
|
|
|
#include "Platform.h"
|
|
|
|
#ifndef DEBUG_INJECT
|
|
#ifndef DEBUG_ALL
|
|
#define DEBUG_INJECT 1
|
|
#else
|
|
#define DEBUG_INJECT DEBUG_ALL
|
|
#endif
|
|
#endif
|
|
|
|
#if DEBUG_INJECT == 0
|
|
#define DBG(...)
|
|
#else
|
|
#define DBG(...) DebugLog(DEBUG_INJECT, __VA_ARGS__)
|
|
#endif
|
|
|
|
UINT32 devices_number = 1;
|
|
UINT32 builtin_set = 0;
|
|
DevPropString *device_inject_string = NULL;
|
|
UINT8 *device_inject_stringdata = NULL;
|
|
UINT32 device_inject_stringlength = 0;
|
|
|
|
//pci_dt_t* nvdevice;
|
|
//SwapBytes16 or 32
|
|
/*
|
|
static UINT16 dp_swap16(UINT16 toswap)
|
|
{
|
|
return (((toswap & 0x00FF) << 8) | ((toswap & 0xFF00) >> 8));
|
|
}
|
|
|
|
static UINT32 dp_swap32(UINT32 toswap)
|
|
{
|
|
return ((toswap & 0x000000FF) << 24) |
|
|
((toswap & 0x0000FF00) << 8 ) |
|
|
((toswap & 0x00FF0000) >> 8 ) |
|
|
((toswap & 0xFF000000) >> 24);
|
|
}
|
|
*/
|
|
|
|
DevPropString *devprop_create_string(VOID)
|
|
{
|
|
// DBG("Begin creating strings for devices:\n");
|
|
device_inject_string = (DevPropString*)AllocateZeroPool(sizeof(DevPropString));
|
|
|
|
if(device_inject_string == NULL)
|
|
return NULL;
|
|
|
|
device_inject_string->length = 12;
|
|
device_inject_string->WHAT2 = 0x01000000;
|
|
return device_inject_string;
|
|
}
|
|
|
|
|
|
CHAR8 *get_pci_dev_path(pci_dt_t *PciDt)
|
|
{
|
|
// DBG("get_pci_dev_path");
|
|
CHAR8* tmp;
|
|
CHAR16* devpathstr = NULL;
|
|
EFI_DEVICE_PATH_PROTOCOL* DevicePath = NULL;
|
|
|
|
DevicePath = DevicePathFromHandle (PciDt->DeviceHandle);
|
|
if (!DevicePath)
|
|
return NULL;
|
|
devpathstr = FileDevicePathToStr(DevicePath);
|
|
tmp = AllocateZeroPool((StrLen(devpathstr)+1)*sizeof(CHAR16));
|
|
UnicodeStrToAsciiStrS(devpathstr, tmp, (StrLen(devpathstr)+1));
|
|
return tmp;
|
|
|
|
}
|
|
|
|
UINT32 pci_config_read32(pci_dt_t *PciDt, UINT8 reg)
|
|
{
|
|
// DBG("pci_config_read32\n");
|
|
EFI_STATUS Status;
|
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
|
PCI_TYPE00 Pci;
|
|
UINT32 res;
|
|
|
|
Status = gBS->OpenProtocol(PciDt->DeviceHandle, &gEfiPciIoProtocolGuid, (VOID**)&PciIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
if (EFI_ERROR(Status)){
|
|
DBG("pci_config_read cant open protocol\n");
|
|
return 0;
|
|
}
|
|
Status = PciIo->Pci.Read(PciIo,EfiPciIoWidthUint32, 0, sizeof(Pci) / sizeof(UINT32), &Pci);
|
|
if (EFI_ERROR(Status)) {
|
|
DBG("pci_config_read cant read pci\n");
|
|
return 0;
|
|
}
|
|
Status = PciIo->Pci.Read (
|
|
PciIo,
|
|
EfiPciIoWidthUint32,
|
|
(UINT64)(reg & ~3),
|
|
1,
|
|
&res
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
DBG("pci_config_read32 failed %r\n", Status);
|
|
return 0;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
UINT32 PciAddrFromDevicePath(EFI_DEVICE_PATH_PROTOCOL* DevicePath)
|
|
{
|
|
return 0;
|
|
}
|
|
//Size = GetDevicePathSize (DevicePath);
|
|
|
|
//dmazar: replaced by devprop_add_device_pci
|
|
|
|
DevPropDevice *devprop_add_device_pci(DevPropString *StringBuf, pci_dt_t *PciDt, EFI_DEVICE_PATH_PROTOCOL *DevicePath)
|
|
{
|
|
// EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
DevPropDevice *device;
|
|
UINT32 NumPaths;
|
|
|
|
if (StringBuf == NULL /* || PciDt == NULL */) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!DevicePath && (PciDt != 0)) {
|
|
DevicePath = DevicePathFromHandle(PciDt->DeviceHandle);
|
|
}
|
|
// DBG("devprop_add_device_pci %s ", DevicePathToStr(DevicePath));
|
|
if (!DevicePath)
|
|
return NULL;
|
|
|
|
device = AllocateZeroPool(sizeof(DevPropDevice));
|
|
if (!device) {
|
|
return NULL;
|
|
}
|
|
|
|
device->numentries = 0x00;
|
|
|
|
//
|
|
// check and copy ACPI_DEVICE_PATH
|
|
//
|
|
if (DevicePath->Type == ACPI_DEVICE_PATH && DevicePath->SubType == ACPI_DP) {
|
|
// CopyMem(&device->acpi_dev_path, DevicePath, sizeof(struct ACPIDevPath));
|
|
device->acpi_dev_path.length = 0x0c;
|
|
device->acpi_dev_path.type = 0x02;
|
|
device->acpi_dev_path.subtype = 0x01;
|
|
device->acpi_dev_path._HID = 0x0a0341d0;
|
|
device->acpi_dev_path._UID = (((ACPI_HID_DEVICE_PATH*)DevicePath)->UID)?0x80:0;
|
|
|
|
// DBG("ACPI HID=%x, UID=%x ", device->acpi_dev_path._HID, device->acpi_dev_path._UID);
|
|
} else {
|
|
// DBG("not ACPI\n");
|
|
FreePool(device);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// copy PCI paths
|
|
//
|
|
for (NumPaths = 0; NumPaths < MAX_PCI_DEV_PATHS; NumPaths++) {
|
|
DevicePath = NextDevicePathNode(DevicePath);
|
|
if (DevicePath->Type == HARDWARE_DEVICE_PATH && DevicePath->SubType == HW_PCI_DP) {
|
|
CopyMem(&device->pci_dev_path[NumPaths], DevicePath, sizeof(struct PCIDevPath));
|
|
// DBG("PCI[%d] f=%x, d=%x ", NumPaths, device->pci_dev_path[NumPaths].function, device->pci_dev_path[NumPaths].device);
|
|
} else {
|
|
// not PCI path - break the loop
|
|
// DBG("not PCI ");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NumPaths == 0) {
|
|
// DBG("NumPaths == 0 \n");
|
|
FreePool(device);
|
|
return NULL;
|
|
}
|
|
|
|
// DBG("-> NumPaths=%d\n", NumPaths);
|
|
device->num_pci_devpaths = (UINT8)NumPaths;
|
|
device->length = (UINT32)(24U + (6U * NumPaths));
|
|
|
|
device->path_end.length = 0x04;
|
|
device->path_end.type = 0x7f;
|
|
device->path_end.subtype = 0xff;
|
|
|
|
device->string = StringBuf;
|
|
device->data = NULL;
|
|
StringBuf->length += device->length;
|
|
|
|
if(!StringBuf->entries) {
|
|
StringBuf->entries = (DevPropDevice**)AllocateZeroPool(MAX_NUM_DEVICES * sizeof(device));
|
|
if(!StringBuf->entries) {
|
|
FreePool(device);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
StringBuf->entries[StringBuf->numentries++] = device;
|
|
|
|
return device;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN devprop_add_value(DevPropDevice *device, CHAR8 *nm, UINT8 *vl, UINTN len)
|
|
{
|
|
UINT32 offset;
|
|
UINT32 off;
|
|
UINT32 length;
|
|
UINT8 *data;
|
|
UINTN i, l;
|
|
UINT32 *datalength;
|
|
UINT8 *newdata;
|
|
|
|
if(!device || !nm || !vl /*|| !len*/) //rehabman: allow zero length data
|
|
return FALSE;
|
|
/* DBG("devprop_add_value %a=", nm);
|
|
for (i=0; i<len; i++) {
|
|
DBG("%02X", vl[i]);
|
|
}
|
|
DBG("\n"); */
|
|
l = AsciiStrLen(nm);
|
|
length = (UINT32)((l * 2) + len + (2 * sizeof(UINT32)) + 2);
|
|
data = (UINT8*)AllocateZeroPool(length);
|
|
if(!data)
|
|
return FALSE;
|
|
|
|
off= 0;
|
|
|
|
data[off+1] = (UINT8)(((l * 2) + 6) >> 8);
|
|
data[off] = ((l * 2) + 6) & 0x00FF;
|
|
|
|
off += 4;
|
|
|
|
for(i = 0 ; i < l ; i++, off += 2) {
|
|
data[off] = *nm++;
|
|
}
|
|
|
|
off += 2;
|
|
l = len;
|
|
datalength = (UINT32*)&data[off];
|
|
*datalength = (UINT32)(l + 4);
|
|
off += 4;
|
|
for(i = 0 ; i < l ; i++, off++) {
|
|
data[off] = *vl++;
|
|
}
|
|
|
|
offset = device->length - (24 + (6 * device->num_pci_devpaths));
|
|
|
|
newdata = (UINT8*)AllocateZeroPool((length + offset));
|
|
if(!newdata)
|
|
return FALSE;
|
|
if((device->data) && (offset > 1)) {
|
|
CopyMem((VOID*)newdata, (VOID*)device->data, offset);
|
|
}
|
|
|
|
CopyMem((VOID*)(newdata + offset), (VOID*)data, length);
|
|
|
|
device->length += length;
|
|
device->string->length += length;
|
|
device->numentries++;
|
|
device->data = newdata;
|
|
|
|
FreePool(data);
|
|
return TRUE;
|
|
}
|
|
|
|
CHAR8 *devprop_generate_string(DevPropString *StringBuf)
|
|
{
|
|
UINTN len = StringBuf->length * 2;
|
|
INT32 i = 0;
|
|
UINT32 x = 0;
|
|
CHAR8 *buffer = (CHAR8*)AllocatePool(len + 1);
|
|
CHAR8 *ptr = buffer;
|
|
|
|
// DBG("devprop_generate_string\n");
|
|
if(!buffer)
|
|
return NULL;
|
|
|
|
AsciiSPrint(buffer, len, "%08x%08x%04x%04x", SwapBytes32(StringBuf->length), StringBuf->WHAT2,
|
|
SwapBytes16(StringBuf->numentries), StringBuf->WHAT3);
|
|
buffer += 24;
|
|
|
|
while(i < StringBuf->numentries) {
|
|
UINT8 *dataptr = StringBuf->entries[i]->data;
|
|
AsciiSPrint(buffer, len, "%08x%04x%04x", SwapBytes32(StringBuf->entries[i]->length),
|
|
SwapBytes16(StringBuf->entries[i]->numentries), StringBuf->entries[i]->WHAT2); //FIXME: wrong buffer sizes!
|
|
|
|
buffer += 16;
|
|
AsciiSPrint(buffer, len, "%02x%02x%04x%08x%08x", StringBuf->entries[i]->acpi_dev_path.type,
|
|
StringBuf->entries[i]->acpi_dev_path.subtype,
|
|
SwapBytes16(StringBuf->entries[i]->acpi_dev_path.length),
|
|
SwapBytes32(StringBuf->entries[i]->acpi_dev_path._HID),
|
|
SwapBytes32(StringBuf->entries[i]->acpi_dev_path._UID));
|
|
|
|
buffer += 24;
|
|
for(x = 0; x < StringBuf->entries[i]->num_pci_devpaths; x++) {
|
|
AsciiSPrint(buffer, len, "%02x%02x%04x%02x%02x", StringBuf->entries[i]->pci_dev_path[x].type,
|
|
StringBuf->entries[i]->pci_dev_path[x].subtype,
|
|
SwapBytes16(StringBuf->entries[i]->pci_dev_path[x].length),
|
|
StringBuf->entries[i]->pci_dev_path[x].function,
|
|
StringBuf->entries[i]->pci_dev_path[x].device);
|
|
buffer += 12;
|
|
}
|
|
|
|
AsciiSPrint(buffer, len, "%02x%02x%04x", StringBuf->entries[i]->path_end.type,
|
|
StringBuf->entries[i]->path_end.subtype,
|
|
SwapBytes16(StringBuf->entries[i]->path_end.length));
|
|
|
|
buffer += 8;
|
|
for(x = 0; x < (StringBuf->entries[i]->length) - (24 + (6 * StringBuf->entries[i]->num_pci_devpaths)); x++) {
|
|
AsciiSPrint(buffer, len, "%02x", *dataptr++);
|
|
buffer += 2;
|
|
}
|
|
i++;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
VOID devprop_free_string(DevPropString *StringBuf)
|
|
{
|
|
INT32 i;
|
|
if(!StringBuf)
|
|
return;
|
|
|
|
for(i = 0; i < StringBuf->numentries; i++) {
|
|
if(StringBuf->entries[i]) {
|
|
if(StringBuf->entries[i]->data) {
|
|
FreePool(StringBuf->entries[i]->data);
|
|
}
|
|
}
|
|
}
|
|
FreePool(StringBuf->entries);
|
|
FreePool(StringBuf);
|
|
// StringBuf = NULL;
|
|
}
|
|
|
|
// Ethernet built-in device injection
|
|
BOOLEAN set_eth_props(pci_dt_t *eth_dev)
|
|
{
|
|
#if DEBUG_INJECT
|
|
CHAR8 *devicepath;
|
|
#endif
|
|
DevPropDevice *device = NULL;
|
|
UINT8 builtin = 0x0;
|
|
BOOLEAN Injected = FALSE;
|
|
UINTN i;
|
|
CHAR8 compatible[64];
|
|
|
|
if (!gSettings.LANInjection) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!device_inject_string) {
|
|
device_inject_string = devprop_create_string();
|
|
}
|
|
#if DEBUG_INJECT
|
|
devicepath = get_pci_dev_path(eth_dev);
|
|
#endif
|
|
if (eth_dev && !eth_dev->used) {
|
|
device = devprop_add_device_pci(device_inject_string, eth_dev, NULL);
|
|
eth_dev->used = TRUE;
|
|
}
|
|
|
|
if (!device) {
|
|
return FALSE;
|
|
}
|
|
// -------------------------------------------------
|
|
// DBG("LAN Controller [%04x:%04x] :: %a\n", eth_dev->vendor_id, eth_dev->device_id, devicepath);
|
|
if (eth_dev->vendor_id != 0x168c && builtin_set == 0) {
|
|
builtin_set = 1;
|
|
builtin = 0x01;
|
|
}
|
|
|
|
if (gSettings.NrAddProperties != 0xFFFE) {
|
|
for (i = 0; i < gSettings.NrAddProperties; i++) {
|
|
if (gSettings.AddProperties[i].Device != DEV_LAN) {
|
|
continue;
|
|
}
|
|
Injected = TRUE;
|
|
|
|
if (!gSettings.AddProperties[i].MenuItem.BValue) {
|
|
//DBG(" disabled property Key: %a, len: %d\n", gSettings.AddProperties[i].Key, gSettings.AddProperties[i].ValueLen);
|
|
} else {
|
|
devprop_add_value(device,
|
|
gSettings.AddProperties[i].Key,
|
|
(UINT8*)gSettings.AddProperties[i].Value,
|
|
gSettings.AddProperties[i].ValueLen);
|
|
//DBG(" added property Key: %a, len: %d\n", gSettings.AddProperties[i].Key, gSettings.AddProperties[i].ValueLen);
|
|
}
|
|
}
|
|
}
|
|
if (Injected) {
|
|
DBG("custom LAN properties injected, continue\n");
|
|
// return TRUE;
|
|
}
|
|
|
|
// DBG("Setting dev.prop built-in=0x%x\n", builtin);
|
|
// devprop_add_value(device, "device_type", (UINT8*)"Ethernet", 9);
|
|
if (gSettings.FakeLAN) {
|
|
UINT32 FakeID = gSettings.FakeLAN >> 16;
|
|
devprop_add_value(device, "device-id", (UINT8*)&FakeID, 4);
|
|
AsciiSPrint(compatible, 64, "pci%x,%x", (gSettings.FakeLAN & 0xFFFF), FakeID);
|
|
LowCase(compatible);
|
|
devprop_add_value(device, "compatible", (UINT8*)&compatible[0], 12);
|
|
FakeID = gSettings.FakeLAN & 0xFFFF;
|
|
devprop_add_value(device, "vendor-id", (UINT8*)&FakeID, 4);
|
|
}
|
|
else if (eth_dev->vendor_id == 0x11AB && eth_dev->device_id == 0x4364)
|
|
{
|
|
UINT32 FakeID = 0x4354;
|
|
devprop_add_value(device, "device-id", (UINT8*)&FakeID, 4);
|
|
}
|
|
|
|
|
|
return devprop_add_value(device, "built-in", (UINT8*)&builtin, 1);
|
|
}
|
|
|
|
#define PCI_IF_XHCI 0x30
|
|
|
|
static UINT8 clock_id = 0;
|
|
static UINT8 builtin = 0x0;
|
|
|
|
static UINT16 current_available = 1200; //mA
|
|
static UINT16 current_extra = 700;
|
|
static UINT16 current_in_sleep = 1000;
|
|
static UINT16 current_available_high = 2100; //mA
|
|
static UINT16 current_extra_high = 3200;
|
|
|
|
BOOLEAN set_usb_props(pci_dt_t *usb_dev)
|
|
{
|
|
#if DEBUG_INJECT
|
|
CHAR8 *devicepath;
|
|
#endif
|
|
DevPropDevice *device = NULL;
|
|
UINT32 fake_devid;
|
|
BOOLEAN Injected = FALSE;
|
|
UINTN i;
|
|
|
|
if (!device_inject_string)
|
|
device_inject_string = devprop_create_string();
|
|
#if DEBUG_INJECT
|
|
devicepath = get_pci_dev_path(usb_dev);
|
|
#endif
|
|
|
|
if (usb_dev && !usb_dev->used) {
|
|
device = devprop_add_device_pci(device_inject_string, usb_dev, NULL);
|
|
usb_dev->used = TRUE;
|
|
}
|
|
|
|
if (!device) {
|
|
return FALSE;
|
|
}
|
|
// -------------------------------------------------
|
|
// DBG("USB Controller [%04x:%04x] :: %a\n", usb_dev->vendor_id, usb_dev->device_id, devicepath);
|
|
// DBG("Setting dev.prop built-in=0x%x\n", builtin);
|
|
|
|
if (gSettings.NrAddProperties != 0xFFFE) {
|
|
for (i = 0; i < gSettings.NrAddProperties; i++) {
|
|
if (gSettings.AddProperties[i].Device != DEV_USB) {
|
|
continue;
|
|
}
|
|
Injected = TRUE;
|
|
|
|
if (!gSettings.AddProperties[i].MenuItem.BValue) {
|
|
//DBG(" disabled property Key: %a, len: %d\n", gSettings.AddProperties[i].Key, gSettings.AddProperties[i].ValueLen);
|
|
} else {
|
|
devprop_add_value(device,
|
|
gSettings.AddProperties[i].Key,
|
|
(UINT8*)gSettings.AddProperties[i].Value,
|
|
gSettings.AddProperties[i].ValueLen);
|
|
//DBG(" added property Key: %a, len: %d\n", gSettings.AddProperties[i].Key, gSettings.AddProperties[i].ValueLen);
|
|
}
|
|
}
|
|
}
|
|
if (Injected) {
|
|
DBG("custom USB properties injected, continue\n");
|
|
// return TRUE;
|
|
}
|
|
|
|
if (gSettings.InjectClockID) {
|
|
devprop_add_value(device, "AAPL,clock-id", (UINT8*)&clock_id, 1);
|
|
clock_id++;
|
|
}
|
|
|
|
fake_devid = usb_dev->device_id & 0xFFFF;
|
|
if ((fake_devid & 0xFF00) == 0x2900) {
|
|
// fake_devid &= 0xFEFF;
|
|
fake_devid &= ~0xFF00;
|
|
fake_devid |= 0x3A00;
|
|
devprop_add_value(device, "device-id", (UINT8*)&fake_devid, 4);
|
|
}
|
|
switch (usb_dev->subclass) {
|
|
case PCI_IF_UHCI:
|
|
devprop_add_value(device, "device_type", (UINT8*)"UHCI", 4);
|
|
break;
|
|
case PCI_IF_OHCI:
|
|
devprop_add_value(device, "device_type", (UINT8*)"OHCI", 4);
|
|
break;
|
|
case PCI_IF_EHCI:
|
|
devprop_add_value(device, "device_type", (UINT8*)"EHCI", 4);
|
|
if (gSettings.HighCurrent) {
|
|
devprop_add_value(device, "AAPL,current-available", (UINT8*)¤t_available_high, 2);
|
|
devprop_add_value(device, "AAPL,current-extra", (UINT8*)¤t_extra_high, 2);
|
|
} else {
|
|
devprop_add_value(device, "AAPL,current-available", (UINT8*)¤t_available, 2);
|
|
devprop_add_value(device, "AAPL,current-extra", (UINT8*)¤t_extra, 2);
|
|
}
|
|
devprop_add_value(device, "AAPL,current-in-sleep", (UINT8*)¤t_in_sleep, 2);
|
|
break;
|
|
case PCI_IF_XHCI:
|
|
devprop_add_value(device, "device_type", (UINT8*)"XHCI", 4);
|
|
if (gSettings.HighCurrent) {
|
|
devprop_add_value(device, "AAPL,current-available", (UINT8*)¤t_available_high, 2);
|
|
devprop_add_value(device, "AAPL,current-extra", (UINT8*)¤t_extra_high, 2);
|
|
} else {
|
|
devprop_add_value(device, "AAPL,current-available", (UINT8*)¤t_available, 2);
|
|
devprop_add_value(device, "AAPL,current-extra", (UINT8*)¤t_extra, 2);
|
|
}
|
|
devprop_add_value(device, "AAPL,current-in-sleep", (UINT8*)¤t_in_sleep, 2);
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return devprop_add_value(device, "built-in", (UINT8*)&builtin, 1);
|
|
}
|