Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ struct _USB_HUB_API {
USB_HUB_RELEASE Release;
};

#define USB_US_LAND_ID 0x0409
#define USB_US_LANG_ID 0x0409

#define DEVICE_PATH_LIST_ITEM_SIGNATURE SIGNATURE_32('d','p','l','i')
typedef struct _DEVICE_PATH_LIST_ITEM {
Expand Down
152 changes: 129 additions & 23 deletions MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ UsbFreeDevDesc (
FreePool (DevDesc->Configs);
}

if (DevDesc->StrDescManufacturerUS != NULL) {
FreePool (DevDesc->StrDescManufacturerUS);
}

if (DevDesc->StrDescProductUS != NULL) {
FreePool (DevDesc->StrDescProductUS);
}

if (DevDesc->StrDescSerialNumberUS != NULL) {
FreePool (DevDesc->StrDescSerialNumberUS);
}

FreePool (DevDesc);
}

Expand Down Expand Up @@ -640,40 +652,89 @@ UsbGetOneString (
EFI_STATUS Status;
UINT8 *Buf;

EFI_USB_STRING_DESCRIPTOR *CachedDesc = NULL;

//
// First get two bytes which contains the string length.
// If the String is cached and LangId = US, just return the cached string descriptor
//
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);
if ((LangId == USB_US_LANG_ID) && (Index > 0)) {
Buf = NULL;

if (Index == UsbDev->DevDesc->Desc.StrManufacturer) {
if (UsbDev->DevDesc->StrDescManufacturerUS != NULL) {
CachedDesc = (EFI_USB_STRING_DESCRIPTOR *)UsbDev->DevDesc->StrDescManufacturerUS;
Buf = AllocateZeroPool (CachedDesc->Length);
CopyMem (Buf, (UINT8 *)CachedDesc, CachedDesc->Length);
}
} else if (Index == UsbDev->DevDesc->Desc.StrProduct) {
if (UsbDev->DevDesc->StrDescProductUS != NULL) {
CachedDesc = (EFI_USB_STRING_DESCRIPTOR *)UsbDev->DevDesc->StrDescProductUS;
Buf = AllocateZeroPool (CachedDesc->Length);
CopyMem (Buf, (UINT8 *)CachedDesc, CachedDesc->Length);
}
} else if (Index == UsbDev->DevDesc->Desc.StrSerialNumber) {
if (UsbDev->DevDesc->StrDescSerialNumberUS != NULL) {
CachedDesc = (EFI_USB_STRING_DESCRIPTOR *)UsbDev->DevDesc->StrDescSerialNumberUS;
Buf = AllocateZeroPool (CachedDesc->Length);
CopyMem (Buf, (UINT8 *)CachedDesc, CachedDesc->Length);
}
} else {
Buf = NULL;
}

if (Buf != NULL) {
return (EFI_USB_STRING_DESCRIPTOR *)Buf;
}
}

//
// Reject if Length even cannot cover itself, or odd because Unicode string byte length should be even.
// Copy the mechanism from Linux Driver to get the better compatibility. see usb_string_sub.
//
Buf = AllocateZeroPool (256);
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, Buf, 255);
if (EFI_ERROR (Status) ||
(Desc.Length < OFFSET_OF (EFI_USB_STRING_DESCRIPTOR, Length) + sizeof (Desc.Length)) ||
(Desc.Length % 2 != 0)
)
(((EFI_USB_STRING_DESCRIPTOR *)Buf)->Length < OFFSET_OF (EFI_USB_STRING_DESCRIPTOR, Length) + sizeof (((EFI_USB_STRING_DESCRIPTOR *)Buf)->Length)) ||
(((EFI_USB_STRING_DESCRIPTOR *)Buf)->Length % 2 != 0))
{
return NULL;
}
DEBUG ((DEBUG_ERROR, "UsbGetOneString: Get 255 bytes path failed, Status = %r\n", Status));
FreePool (Buf);
Buf = NULL;

Buf = AllocateZeroPool (Desc.Length);
//
// First get two bytes which contains the string length.
//
Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);

if (Buf == NULL) {
return NULL;
}
//
// Reject if Length even cannot cover itself, or odd because Unicode string byte length should be even.
//
if (EFI_ERROR (Status) ||
(Desc.Length < OFFSET_OF (EFI_USB_STRING_DESCRIPTOR, Length) + sizeof (Desc.Length)) ||
(Desc.Length % 2 != 0)
)
{
return NULL;
}

Status = UsbCtrlGetDesc (
UsbDev,
USB_DESC_TYPE_STRING,
Index,
LangId,
Buf,
Desc.Length
);
Buf = AllocateZeroPool (Desc.Length);

if (EFI_ERROR (Status)) {
FreePool (Buf);
return NULL;
if (Buf == NULL) {
return NULL;
}

Status = UsbCtrlGetDesc (
UsbDev,
USB_DESC_TYPE_STRING,
Index,
LangId,
Buf,
Desc.Length
);

if (EFI_ERROR (Status)) {
FreePool (Buf);
return NULL;
}
}

return (EFI_USB_STRING_DESCRIPTOR *)Buf;
Expand Down Expand Up @@ -725,6 +786,51 @@ UsbBuildLangTable (

UsbDev->TotalLangId = (UINT16)Max;

//
// Some SMART Technologies key says that it supports LangId=0 only, but it
// responds to USB_US_LANG_ID (English). This is a workaround for all such keys.
//
if ((UsbDev->TotalLangId == 1) && (UsbDev->LangId[0] == 0)) {
UsbDev->LangId[0] = USB_US_LANG_ID;
}

//
// Some devices need to get the string immediately after SW get the first String descriptor
// for supported language.
//
gBS->FreePool (Desc);
Desc = NULL;
if (UsbDev->DevDesc->Desc.StrManufacturer != 0) {
Desc = UsbGetOneString (UsbDev, UsbDev->DevDesc->Desc.StrManufacturer, UsbDev->LangId[0]);
if (UsbDev->LangId[0] == USB_US_LANG_ID) {
UsbDev->DevDesc->StrDescManufacturerUS = (UINT8 *)Desc;
}

Desc = NULL;
}

if (UsbDev->DevDesc->Desc.StrProduct != 0) {
Desc = UsbGetOneString (UsbDev, UsbDev->DevDesc->Desc.StrProduct, UsbDev->LangId[0]);
if (UsbDev->LangId[0] == USB_US_LANG_ID) {
UsbDev->DevDesc->StrDescProductUS = (UINT8 *)Desc;
}

Desc = NULL;
}

if (UsbDev->DevDesc->Desc.StrSerialNumber != 0) {
Desc = UsbGetOneString (UsbDev, UsbDev->DevDesc->Desc.StrSerialNumber, UsbDev->LangId[0]);
if (UsbDev->LangId[0] == USB_US_LANG_ID) {
UsbDev->DevDesc->StrDescSerialNumberUS = (UINT8 *)Desc;
}

Desc = NULL;
}

if (Desc == NULL) {
return Status;
}

ON_EXIT:
gBS->FreePool (Desc);
return Status;
Expand Down
4 changes: 4 additions & 0 deletions MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ typedef struct {
typedef struct {
EFI_USB_DEVICE_DESCRIPTOR Desc;
USB_CONFIG_DESC **Configs;
UINT8 *BOSDesc;
UINT8 *StrDescManufacturerUS;
UINT8 *StrDescProductUS;
UINT8 *StrDescSerialNumberUS;
} USB_DEVICE_DESC;

/**
Expand Down
Loading