#include <Uefi.h> #include <Library/UefiLib.h> //#include <Library/ShellCEntryLib.h> #include <Library/MemoryAllocationLib.h> #include <Library/BaseMemoryLib.h> #include <Protocol/UsbIo.h>
#include <Protocol/AmiUsbController.h>
#include <AmiLib.h> #include <AmiDxeLib.h> #include <AmiDxeLib.h>
#include <Protocol/Smbios.h> #include "EfiKey.h"
#include <Uefi.h> #include <Library/UefiLib.h> #include <IndustryStandard/SmBios.h> //#include <Library/UefiShellDebug1CommandsLib.h> //#include <Library/LibSmbiosView.h>
#include "HomeWorkDxe.h"
extern EFI_BOOT_SERVICES *gBS; extern EFI_HANDLE gImageHandle;
#include <Library/MemoryAllocationLib.h> #include <Library/BaseMemoryLib.h> #include <Protocol/UsbIo.h>
#include <Protocol/AmiUsbController.h>
#include <AmiDxeLib.h>
#include <Protocol/Smbios.h> #include "EfiKey.h"
EFI_GUID gEfiUsbIoProtocolGuid = { 0x2B2F68D6, 0x0CD2, 0x44CF, { 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 }};
EFI_GUID gEfiSimpleTextInputExProtocolGuid = {0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa }};
EFI_GUID ggEfiHomeWorkProtocolGuid = {0x47590bea, 0x6178, 0x498d, { 0xa9, 0x5, 0x3c, 0xe6, 0x63, 0xc3, 0x84, 0xd9 }};
#if 1
//************************************************************************* //<AMI_PHDR_START> // // Name: Sprintf // // Description: // UINTN Sprintf(OUT CHAR8 *Buffer, IN CHAR8 *Format, IN ...) produces a // null-terminated ASCII string in the output Buffer. The ASCII string is // produced by parsing the format string specified by Format. Arguments are // pulled from the variable argument list based on the contents of the format // string. The number of ASCII characters in the produced output buffer is // returned, not including the null-terminator. See notes for format string // information. // // Input: // OUT CHAR8 *Buffer // Pointer to a null-terminated output ASCII string buffer. User is // responsible for allocating the necessary memory resources! // // IN CHAR8 *Format // Pointer to a null-terminated format ASCII string. // // IN ... // Variable argument list which provides the data/variables used within the // format string. // // Output: // UINTN number of ASCII characters in the produced output buffer, not // including the null-terminator. // // Modified: // // Referrals: // va_start // Sprintf_va_list // va_end // // Notes: // Objects inside the format string have the following syntax. // %[flags][width]type // // *** [flags] *** // // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // . Flag . Description // . . // . - . The field is left justified. If flag is not specified, then // . . the field is right justified. // . . // . space . Prefix a space character to a number. Only valid for types X, // . . x, and d. // . . // . + . Prefix a plus character to a number. Only valid for types X, // . . x, and d. If both space and `+' are specified, then space is // . . ignored. // . . // . 0 . Pad with `0' characters to the left of a number. Only valid // . . for types X, x, and d. // . . // . L, l . The number being printed is a UINT64. Only valid for types X, // . . x, and d. If this flag is not specified, then the number being // . . printed is an int. // . . // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // // NOTE // All invalid [flags] are ignored. // // *** [width] *** // // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // . Width . Description // . . // . * . The width of the field is specified by a UINTN argument in the // . . argument list. // . . // . Number . The number specified as a decimal value represents the width of // . . the field. // . . // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // // NOTE // If [width] is not specified, then a field width of 0 is assumed. // // *** type *** // // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // . Type . Description // . . // . % . Print a `%'. // . . // . c . The argument is an ASCII character. // . . // . x . The argument is a hexadecimal number. The characters used are // . . 0..9 and a..f. If the flag `l' is not specified, then the // . . argument is assumed to be an int. // . . // . X . The argument is a hexadecimal number. The characters used are // . . 0..9 and A..F. If the flag `l' is not specified, then the // . . argument is assumed to be an int. // . . // . d . The argument is a decimal number. If the flag `l' is not // . . specified, then the argument is assumed to be an int. // . . // . i . The same as `d'. // . . // . s . The argument is a pointer to null-terminated ASCII string. // . . // . a . The same as `s'. // . . // . S . The argument is a pointer to a null-terminated Unicode string. // . . // . g . The argument is a pointer to a GUID structure. The GUID is // . . printed in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. // . . // . G . The argument is a pointer to a GUID structure. The GUID is // . . printed in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. // . . // . r . The argument is an EFI_STATUS value. This value is converted // . . to a string. // . . // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // // NOTE // All invalid type characters are copied into the result string. // //<AMI_PHDR_END> //*************************************************************************
int macdbg_dmphex_kernel(const char* buff_in, int len) { int retval = 0; int x, y, tot, lineoff; const char* curr; CHAR16 buff[1024]; UINTN index;
DEBUG( (EFI_D_INFO, "dump addr -> 0x%x: \n", buff_in) ); //DEBUG((EFI_D_INFO, "len = 0x%x.\n", len ));
lineoff = 0; curr = buff_in; tot = 0;
for( x = 0; x+16 < len; ){ index = 0x00; memset( buff, 0x00, sizeof(buff) ); Swprintf( &buff[index], L"0x%04x: ", lineoff ); index = Wcslen(buff);
//DEBUG((EFI_D_INFO, "index = %d\n", index )); //DEBUG((EFI_D_INFO, "debug.0 = %s\n", buff )); //DEBUG((EFI_D_INFO, "debug.1 = %S\n", buff ));
for( y = 0; y < 16; y++ ){ Swprintf( &buff[index], L"%02x ", (unsigned char)*(curr + y) ); index = Wcslen(buff); }
//DEBUG((EFI_D_INFO, "debug.2 = %s\n", buff ));
Swprintf( &buff[index], L"%s", L" " ); index = Wcslen(buff); for( y = 0; y < 16; y++ ){ char c; c = *(curr + y); if( c > 31 && c < 127 ){ Swprintf( &buff[index], L"%c", c ); }else{ Swprintf( &buff[index], L"%c", L'.' ); } index = Wcslen(buff); tot++; } curr += 16; x += 16; lineoff+=16; Swprintf( &buff[index], L"%s", L"\n" ); //printk("%s", buff);
//DEBUG((EFI_D_INFO, "debug.2 = %s\n", buff )); DEBUG((EFI_D_INFO, "%s", buff)); //DEBUG((EFI_D_INFO, "debug.3 = %S\n", buff )); } //do last line //Ser_Printf("tot %d.\r\n", tot ); //Ser_Printf("len %d.\r\n", len ); index = 0x00; memset( buff, 0x00, sizeof(buff) ); if( tot < len ){ curr = (buff_in + tot); Swprintf( &buff[index], L"0x%04x: ", lineoff ); index = Wcslen(buff); for( y = 0; y < (len - tot); y++ ){ Swprintf( &buff[index], L"%02x ", (unsigned char)*(curr + y) ); index = Wcslen(buff); } //padding with spaces //printk("(len - tot) %d.\r\n", (len - tot) ); if( (len - tot) < 16 ){ for( y = 0; y<(16-(len-tot)); y++ ){ Swprintf( &buff[index], L"%s", L" " ); index = index + 3; } } Swprintf( &buff[index], L"%s", L" " ); index = Wcslen(buff); //Ser_Printf("(len - tot) %d.\r\n", (len - tot) ); for( y = 0; y < (len - tot); y++ ){ char c; c = *(curr + y); if( c > 31 && c < 127 ){ Swprintf( &buff[index], L"%c", c ); }else{ Swprintf( &buff[index], L"%c", L'.' ); } index = Wcslen(buff); } } Swprintf( &buff[index], L"%s", L"\n" ); //printk("%s", buff); DEBUG((EFI_D_INFO, "%s\n", buff)); return retval; }
#endif
/** Return SMBIOS string for the given string number.
@param[in] Smbios Pointer to SMBIOS structure. @param[in] StringNumber String number to return. -1 is used to skip all strings and point to the next SMBIOS structure.
@return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == -1 **/ CHAR8* LibGetSmbiosString ( IN SMBIOS_STRUCTURE_POINTER *Smbios, IN UINT16 StringNumber ) { UINT16 Index; CHAR8 *String;
ASSERT (Smbios != NULL);
// // Skip over formatted section // String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length);
// // Look through unformated section // for (Index = 1; Index <= StringNumber; Index++) { if (StringNumber == Index) { return String; } // // Skip string // for (; *String != 0; String++); String++;
if (*String == 0) { // // If double NULL then we are done. // Return pointer to next structure in Smbios. // if you pass in a -1 you will always get here // Smbios->Raw = (UINT8 *)++String; return NULL; } }
return NULL; }
//********************************************************************** //<AMI_PHDR_START> // // Procedure: EfiLibGetSystemConfigurationTable // // Description: Get table from configuration table by name // // Input: IN EFI_GUID *TableGuid, // IN OUT VOID **Table // // Output: EFI_STATUS // // Modified: // // Referrals: // // Notes: //<AMI_PHDR_END> //********************************************************************** EFI_STATUS EfiLibGetSystemConfigurationTable( IN EFI_GUID *TableGuid, IN OUT VOID **Table ) { UINTN Index;
*Table = NULL;
for ( Index = 0; Index < gST->NumberOfTableEntries; Index++ ) { if ( !CompareMem( TableGuid, &(gST->ConfigurationTable[Index].VendorGuid), sizeof(EFI_GUID))) { *Table = gST->ConfigurationTable[Index].VendorTable; return EFI_SUCCESS; } }
return EFI_NOT_FOUND; }
void test_fuck(void) { CHAR16 debug_buff[128]; UINTN index; int len; memset( debug_buff, 0x00, sizeof(debug_buff) );
index = 0x00; Swprintf( &debug_buff[index], L"0x%04x: ", 0x1234 ); index = Wcslen(debug_buff); len = sizeof(debug_buff); macdbg_dmphex_kernel((const char *)debug_buff, len );
DEBUG( (EFI_D_INFO, "index = %d\n", index) ); DEBUG( (EFI_D_INFO, "in test_fuck 4 = %s\n", debug_buff) );
}
EFI_STATUS test_smbios_table() { EFI_STATUS Status; SMBIOS_TABLE_ENTRY_POINT *mSmbiosTable = NULL; SMBIOS_STRUCTURE_POINTER m_SmbiosStruct; SMBIOS_STRUCTURE_POINTER *mSmbiosStruct = &m_SmbiosStruct; SMBIOS_STRUCTURE_POINTER Smbios; SMBIOS_STRUCTURE_POINTER SmbiosEnd; UINT8 *Raw; UINT16 Handle1 = 0; UINT8 *Buffer1; UINT16 Length1;
UINT16 *Handle; UINT8 **Buffer; UINT16 *Length; UINT8 Type; mSmbiosTable = NULL; //Get SMBIOS table from System Configure table Status = EfiLibGetSystemConfigurationTable(&gEfiSmbiosTableGuid,(VOID**)&mSmbiosTable); if (mSmbiosTable == NULL){ Print(L"%r.\n",Status); } //Init SMBIOS structure table address mSmbiosStruct->Raw = (UINT8 *)(UINTN)(mSmbiosTable->TableAddress); //Find the structure Handle = &Handle1; Length = &Length1; Buffer = &Buffer1; *Length = 0; Smbios.Hdr = mSmbiosStruct->Hdr; SmbiosEnd.Raw = Smbios.Raw + mSmbiosTable->TableLength; Print(L"TableLenth:%02d\n",mSmbiosTable->TableLength); while (Smbios.Raw < SmbiosEnd.Raw){ if (Smbios.Hdr->Handle == *Handle){ Raw = Smbios.Raw; Type = Smbios.Hdr->Type; //Walk to next structure LibGetSmbiosString(&Smbios,(UINT16)(-1)); //Length = Next structure head - this structure head *Length = (UINT16)(Smbios.Raw - Raw); *Buffer = Raw; //update with the next structure handle. if (Smbios.Raw < SmbiosEnd.Raw){ *Handle = Smbios.Hdr->Handle; } else{ *Handle = (UINT16)(-1); } DEBUG( (EFI_D_INFO, "Handle:0x%04x Type:0x%02x Address:%08x Length:%04x.\n", *Handle - 1, Type, *Buffer, *Length) ); macdbg_dmphex_kernel(*Buffer, *Length ); } } *Handle = (UINT16)(-1); return EFI_SUCCESS; }
#if 1 VOID HomeWorkDxeProtocolCallback( void ) { EFI_STATUS Status; EFI_HOMEWORKINTERFACE_PROTOCOL *HomeworkProtocolinterface; //step.2 DEBUG( (EFI_D_INFO, "in HomeWorkDxeProtocolCallback\n"));
DEBUG( (EFI_D_INFO, "gEfiHomeWorkProtocolGuid : %g\n", ggEfiHomeWorkProtocolGuid ) ); //CoreLocateProtocol Status = gBS->LocateProtocol(&ggEfiHomeWorkProtocolGuid, NULL, &HomeworkProtocolinterface );
DEBUG((EFI_D_INFO,"HomeWorkPciread Status: %d\n",Status)); if (!EFI_ERROR(Status)) { //step.3 Status = HomeworkProtocolinterface->HomeWork_interface_func_0(0x55); } } #endif
/* * BootOrder.c * * Created on: 2018年3月14日 * Author: */ #include <Uefi.h> #include <Library/UefiRuntimeServicesTableLib.h> #include <Library/UefiLib.h> //#include "UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h"
#include <Protocol/DevicePathToText.h> #include <Library/UefiRuntimeServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/BaseLib.h> #include <Library/UefiLib.h> #include <Library/PrintLib.h> #include <Uefi.h> extern EFI_BOOT_SERVICES *gBS;
EFI_GUID ggEfiDevicePathToTextProtocolGuid = { 0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c };
//EFI_GUID ggEfiHomeWorkProtocolGuid = //{0x47590bea, 0x6178, 0x498d, //{ 0xa9, 0x5, 0x3c, 0xe6, 0x63, 0xc3, 0x84, 0xd9 }};
VOID MmBootDev (void) { UINT16 *VariablePtr; UINTN VariableSize = 0; EFI_STATUS Status; UINTN Count; EFI_LOAD_OPTION *EfiLoadOption; UINTN OptionSize = 0; CHAR16 a[100]; UINTN Index; UINT8 NameLen; EFI_DEVICE_PATH_PROTOCOL *pDevicePathProcotol; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *pDevicePath2TextProtocol; CHAR16 *pStrDevicePath; EfiLoadOption = NULL; VariablePtr = NULL; pStrDevicePath = NULL; //get bootcurrent Status = gRT->GetVariable (L"BootCurrent", &gEfiGlobalVariableGuid, NULL, &VariableSize, VariablePtr); if( Status == EFI_BUFFER_TOO_SMALL ){ Status = gBS->AllocatePool (EfiBootServicesData, VariableSize, &VariablePtr); } gBS->SetMem(VariablePtr ,VariableSize, 0); Status = gRT->GetVariable (L"BootCurrent", &gEfiGlobalVariableGuid, NULL, &VariableSize, VariablePtr); macdbg_dmphex_kernel( (const char *)VariablePtr, (int)VariableSize ); UnicodeSPrint (a, sizeof (L"Boot1234"), L"Boot%04x", *VariablePtr); Print (L"1 = %s.\r\n",a); //get bootcurrent option. Status = gRT->GetVariable (a, &gEfiGlobalVariableGuid, NULL, &OptionSize, EfiLoadOption); if( Status == EFI_BUFFER_TOO_SMALL ){ Status = gBS->AllocatePool (EfiBootServicesData, OptionSize, &EfiLoadOption); } gBS->SetMem(EfiLoadOption ,OptionSize, 0); Status = gRT->GetVariable (a, &gEfiGlobalVariableGuid, NULL, &OptionSize, EfiLoadOption); macdbg_dmphex_kernel( (const char *)EfiLoadOption, (int)OptionSize ); Print (L" DeviceName:%s\r\n",((UINT8*)EfiLoadOption+6)); //get device path NameLen = (UINT8)StrLen((UINT16*)EfiLoadOption + 3); DEBUG((EFI_D_INFO,"ShellAppMain NameLen: %x\n",NameLen)); Status = gBS->LocateProtocol(&ggEfiDevicePathToTextProtocolGuid, NULL, (VOID**)&pDevicePath2TextProtocol); pDevicePathProcotol = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)EfiLoadOption+ 6 + 2*(NameLen+1)); pStrDevicePath = pDevicePath2TextProtocol->ConvertDevicePathToText (pDevicePathProcotol, TRUE, TRUE); Print (L" DevicePath:%s\r\n",pStrDevicePath);
Print (L" DevicePath:%x\r\n",pStrDevicePath);
//get boot order. Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &VariableSize, VariablePtr); Count = VariableSize / sizeof(UINT16); Index = Count - 1; if (Status == EFI_BUFFER_TOO_SMALL) Status = gBS->AllocatePool (EfiBootServicesData, VariableSize, &VariablePtr); gBS->SetMem(VariablePtr ,VariableSize, 0); Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &VariableSize, VariablePtr); while (Count--) { UnicodeSPrint (a, sizeof (L"Boot1234"), L"Boot%04x", VariablePtr[ Index - Count]); Print (L"%s\r\n",a); // get boot option. Status = gRT->GetVariable (a, &gEfiGlobalVariableGuid, NULL, &OptionSize, EfiLoadOption); if (Status == EFI_BUFFER_TOO_SMALL) Status = gBS->AllocatePool (EfiBootServicesData, OptionSize, &EfiLoadOption); gBS->SetMem(EfiLoadOption ,OptionSize, 0); Status = gRT->GetVariable (a, &gEfiGlobalVariableGuid, NULL, &OptionSize, EfiLoadOption); Print (L" DeviceName:%s\r\n",((UINT8*)EfiLoadOption+6)); //get device path NameLen = (UINT8)StrLen((UINT16*)EfiLoadOption + 3); Status = gBS->LocateProtocol(&ggEfiDevicePathToTextProtocolGuid, NULL, (VOID**)&pDevicePath2TextProtocol); pDevicePathProcotol = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)EfiLoadOption+ 6 + 2*(NameLen+1)); pStrDevicePath = pDevicePath2TextProtocol->ConvertDevicePathToText (pDevicePathProcotol, TRUE, TRUE); Print (L" DevicePath:%s\r\n",pStrDevicePath); Print (L" DevicePath:%x\r\n",pStrDevicePath); } gBS->FreePool(pStrDevicePath); gBS->FreePool(EfiLoadOption); gBS->FreePool(VariablePtr);
//此处代码有内存泄漏的毛病 这个玩意多次申请 却只是释放了一次
//虽然代码 有点瑕疵 但是对于初学bios的我来说 还是有参考意义的 }
INTN EFIAPI ShellAppMain( void ) { EFI_STATUS Status; IN OUT UINTN DataSize; OUT VOID *pData; UINT32 Attributes; CHAR16 *InputStr; UINT64 Data; DataSize = 0; pData = NULL; InputStr = NULL; Data = 0; DEBUG((EFI_D_INFO,"ShellAppMain pData: %x\n",pData)); Status = gRT->GetVariable(L"BootOrder", &gEfiGlobalVariableGuid, &Attributes, &DataSize,pData); DEBUG((EFI_D_INFO,"ShellAppMain Status: %d\n",Status)); DEBUG((EFI_D_INFO,"ShellAppMain Status: %r\n",Status)); DEBUG((EFI_D_INFO,"ShellAppMain DataSize: %d\n",DataSize)); DEBUG((EFI_D_INFO,"ShellAppMain pData1: %x\n",pData)); if( Status == EFI_BUFFER_TOO_SMALL ){ Status = gBS->AllocatePool(EfiBootServicesData, DataSize, &pData); DEBUG((EFI_D_INFO,"ShellAppMain pData2: %x\n",pData)); Status = gRT->GetVariable(L"BootOrder", &gEfiGlobalVariableGuid, &Attributes, &DataSize,pData); } DEBUG((EFI_D_INFO,"ShellAppMain Status1: %d\n",Status)); macdbg_dmphex_kernel( (const char *)pData, 12 ); //DumpHex(0, 2, DataSize, pData);
MmBootDev();
#if 0 ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr); if (EFI_ERROR (ShellConvertStringToUint64 (InputStr, &Data, TRUE, TRUE))) { Print(L"input data error.\r\n"); return EFI_SUCCESS; } #endif
//((UINT64*)pData)[0] = Data; //Status = gRT->SetVariable(L"BootOrder", &gEfiGlobalVariableGuid, Attributes, DataSize, pData); //DumpHex(0, 2, DataSize, pData); return EFI_SUCCESS; }
EFI_STATUS UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; Status = EFI_SUCCESS; DEBUG( (EFI_D_WARN, "start UefiMain...\n") );
ShellAppMain();
//HomeWorkDxeProtocolCallback();
return EFI_SUCCESS; }
#if 0
//xxvv
EFI_STATUS UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_SMBIOS_HANDLE SmbiosHandle = 0; EFI_SMBIOS_TABLE_HEADER *Record; EFI_SMBIOS_PROTOCOL *Smbios; UINTN OrigStringNumber = 5; CHAR8 *AsciiData = "smbios_test_str = 12345"; DEBUG( (EFI_D_WARN, "start UefiMain...\n") );
Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios); Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
DEBUG( (EFI_D_INFO, "gEfiSmbiosProtocolGuid : %g\n", gEfiSmbiosProtocolGuid ) );
DEBUG( (EFI_D_INFO, "Type : %x\n", Record->Type) ); DEBUG( (EFI_D_INFO, "Length : %x\n", Record->Length) ); DEBUG( (EFI_D_INFO, "Handle : %x\n", Record->Handle) ); macdbg_dmphex_kernel( (const char *)Record, 256 ); Status = Smbios->UpdateString (Smbios, &SmbiosHandle, &OrigStringNumber, AsciiData); macdbg_dmphex_kernel((const char *)Record, 256 ); return EFI_SUCCESS; test_smbios_table(); return EFI_SUCCESS; }
#endif
直接修改bios代码的方法去熟悉bios源码的效率 太低
每次必须整体编译 然后 烧录 固件
然后插上spi flash
重启
重启之后 还得重新校准 sdram
然后又重启 保存 内存训练的参数
。。。。。。
编译一个shell efi文件 是一个不错的选择
无需重烧固件
efi模块拷贝到u盘
在shell下直接执行efi文件
类似于linux下的驱动模块 ko
此模式对于熟悉bios代码有用 一般初学 无需修改 bios的那些协议
只是在模块中调用协议即可