搜尋此網誌

2013年2月28日 星期四

Str processing functions --(1)

/*Translate str(decimal) to unsigned long value.*/
unsigned long str_to_dec_u32(char *Strbuf, unsigned long *pSUM)

{
if ((*Strbuf >= 0x30) && (*Strbuf <= 0x39)) {
unsigned long ReturnValue = str_to_dec_u32((Strbuf + 1),pSUM);
*pSUM += (*Strbuf % 0x10) * ReturnValue;
return ReturnValue * 10;
}
else {
*pSUM = 0;
return 1;
}
}


/*Translate str(hexadecimal) to unsigned long value.*/
unsigned long str_to_hex_u32(char *Strbuf, unsigned long *pSUM)

{
if ((*Strbuf >= '0') && (*Strbuf <= '9')) {
unsigned long ReturnValue = str_to_hex_u32((Strbuf + 1), pSUM);
*pSUM += (*Strbuf - 0x30) * ReturnValue;
return ReturnValue * 0x10;
} else if ((*Strbuf >= 'a') && (*Strbuf <= 'f')) {
unsigned long ReturnValue = str_to_hex_u32((Strbuf + 1), pSUM);
*pSUM += (*Strbuf - 0x57) * ReturnValue;
return ReturnValue * 0x10;
} else if ((*Strbuf >= 'A') && (*Strbuf <= 'F')) {
unsigned long ReturnValue = str_to_hex_u32((Strbuf + 1), pSUM);
*pSUM += (*Strbuf - 0x37) * ReturnValue;
return ReturnValue * 0x10;
} else {
*pSUM = 0;
return 1;
}
}

/*count str length.*/
int strlen(const char *s)

{
const char *sc;

for (sc = s; *sc != '\0'; ++sc)
/* nothing */;
return (int)(sc - s);
}


/**
 * strstr - Find the first substring in a %NUL terminated string
 * @s1: The string to be searched
 * @s2: The string to search for
 */
char *strstr(const char *s1, const char *s2)
{
int l1, l2;

l2 = strlen(s2);
if (!l2)
return (char *)s1;
l1 = strlen(s1);
while (l1 >= l2) {
l1--;
if (!memcmp(s1, s2, l2))
return (char *)s1;
s1++;
}
return NULL;
}


/*Check whether it is decimal.*/
unsigned char str_isdigit(char *str_buf)
{
    int i;
    for (i = 0; i < strlen(str_buf); i++) {
        if(!((*(str_buf + i) >= '0') && (*(str_buf + i) <= '9')))
            return 0;
    }
    return 1;
}

/*Check whether it is hexadecimal.*/
unsigned char str_isxdigit(char *str_buf)
{
    int i;
    for (i = 0; i < strlen(str_buf); i++) {
        if(!(
        ((*(str_buf + i) >= '0') && (*(str_buf + i) <= '9'))
        || ((*(str_buf + i) >= 'a') && (*(str_buf + i) <= 'f'))
        || ((*(str_buf + i) >= 'A') && (*(str_buf + i) <= 'F'))
        ))
            return 0;
    }
    return 1;
}

/*Translate str(decimal or hexadecimal) to unsigned long value.*/
int str_to_u32(char *Strbuf, unsigned long *pSUM)
{
unsigned long temp_u32;
char *str = Strbuf;
if ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
str = &str[2];
if (str_isxdigit(str)) {
str_to_hex_u32(str, &temp_u32);
*pSUM = temp_u32;
} else {
return 0x01;
}
} else {
if (str_isdigit(str)) {
str_to_dec_u32(str, &temp_u32);
*pSUM = temp_u32;
} else {
return 0x01;
}
}
return 0x00;
}

2013年2月26日 星期二

fopen(),fclose(),fseek(),fwrite(),fread(),fgetc(),fput() --- EFI/UEFI實作


#define FILE EFI_LIST_ENTRY
#define MAX_FILE_LIST_POINT_BUFF_SIZE  256
FILE FileList_Buffer[MAX_FILE_LIST_POINT_BUFF_SIZE];
UINTN FileList_Count = 0;
/*************************************************************************/
FILE *fopen(const char *filename, const char *mode )
{
    FILE *ptr_file_list = &FileList_Buffer[FileList_Count];
    EFI_STATUS          Status;
    CHAR16                VarStr[256];
    CHAR16                ModeStr[256];

    EFI_LIST_ENTRY       *Link;
    SHELL_FILE_ARG      *Arg;
    UINTN                      Index;
    BOOLEAN                 IsSameFile;

    if (FileList_Count >= MAX_FILE_LIST_POINT_BUFF_SIZE)
        return NULL;

    ascii_str_to_unicode_str((CHAR8 *)mode, ModeStr);

    if ((strcmp (mode, "w") != 0) && (strcmp (mode, "a") != 0) && (strcmp (mode, "r") != 0)) {
        Print (L"=>No Supported this mode(%s)\n", ModeStr);
        return NULL;
    }

    InitializeListHead (ptr_file_list);

    ascii_str_to_unicode_str((CHAR8 *)filename, VarStr);

    Status = ShellFileMetaArg (VarStr, ptr_file_list);

    if (EFI_ERROR (Status) || IsListEmpty (ptr_file_list)) {
      Print (L"=>fopen error(%x)\n", Status);
      return NULL;
    }

    IsSameFile = FALSE;
    for (Link = ptr_file_list->Flink; Link != ptr_file_list && SI->RedirArgc; Link = Link->Flink) {
        BREAK_LOOP_ON_ESC ();
        Arg = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
        IsSameFile  = FALSE;
        for (Index = 1; Index < SI->RedirArgc; Index += 2) {
            if (!EFI_ERROR (LibCompareFile (Arg->FullName, SI->RedirArgv[Index], &IsSameFile)) && IsSameFile) {
                break;
            }
        }

        if (IsSameFile) {
            break;
        }
    }

    if (!IsSameFile) {
        for (Link = ptr_file_list->Flink; Link != ptr_file_list; Link = Link->Flink) {
            BREAK_LOOP_ON_ESC ();
            Arg = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
            if ((Arg->Status == EFI_NOT_FOUND) && ((strcmp (mode, "w") == 0) || (strcmp (mode, "a") == 0))) {
                    Status = Arg->Parent->Open (
                              Arg->Parent,
                              HiiHandle,
                              Arg->FileName,
                              EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
                              0 /*Directory:EFI_FILE_DIRECTORY or file:0*/
                              );
                    if (!EFI_ERROR (Status)) {
                        ShellFreeFileList (ptr_file_list);
                        Status = ShellFileMetaArg (VarStr, ptr_file_list);
                        if (EFI_ERROR (Status)) {
                            Print (L"=>Can't create the file(%s).\n", VarStr);
                            return NULL;
                        }
                    } else {
                        Print (L"=>Parent Can't create the file(%s).\n", Arg->FileName);
                        return NULL;
                    }

            } if ((Arg->Status == EFI_NOT_FOUND) && (strcmp (mode, "r") == 0)) {
                   ShellFreeFileList (ptr_file_list);
                   return NULL;
            }
        }
    } else {
        Status = EFI_REDIRECTION_SAME;
    }

    FileList_Count ++;

    return EFI_ERROR(Status) ? NULL : ptr_file_list;
}
/*************************************************************************/
int fclose(FILE *ptr_file_list)
{
    ShellFreeFileList (ptr_file_list);
    return 0;
}
/*************************************************************************/
long fseek( FILE *ptr_file_list, long offset, int where )
{
    EFI_STATUS             Status = EFI_SUCCESS;
    EFI_LIST_ENTRY       *Link;
    SHELL_FILE_ARG      *Arg;
    UINTN                      Index;
    BOOLEAN                 IsSameFile;
    UINT64                    CurrentPosition = 0;

    IsSameFile = FALSE;
    for (Link = ptr_file_list->Flink; Link != ptr_file_list && SI->RedirArgc; Link = Link->Flink) {
        BREAK_LOOP_ON_ESC ();
        Arg         = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
        IsSameFile  = FALSE;
        for (Index = 1; Index < SI->RedirArgc; Index += 2) {
            if (!EFI_ERROR (LibCompareFile (Arg->FullName, SI->RedirArgv[Index], &IsSameFile)) && IsSameFile) {
                break;
            }
        }

        if (IsSameFile) {
            break;
        }
    }

    if (!IsSameFile) {
        for (Link = ptr_file_list->Flink; Link != ptr_file_list; Link = Link->Flink) {
            BREAK_LOOP_ON_ESC ();
            Arg     = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
            Status = Arg->Status;
            if (!EFI_ERROR (Status)) {
                EFI_FILE_HANDLE Handle;
                Handle = Arg->Handle;

                switch(where) {
                    case SEEK_SET:
                        Handle->SetPosition (Handle, offset);
                        break;
                    case SEEK_CUR:
                        Handle->GetPosition (Handle, &CurrentPosition);
                        Handle->SetPosition (Handle, CurrentPosition + offset);
                        break;
                    case SEEK_END:
                        Handle->SetPosition (Handle, Arg->Info->FileSize - offset);
                        break;
                    default:
                        Status = EFI_INVALID_PARAMETER;
                        break;
                }
            }
        }
    } else {
        Status = EFI_REDIRECTION_SAME;
    }

    return (!EFI_ERROR (Status)) ? 0 : -1;
}
/*************************************************************************/
EFI_STATUS
test_WriteFile (
    SHELL_FILE_ARG  *Arg,
    const void *buf,
    UINTN Size
  )
{
  EFI_STATUS      Status;
  CHAR16          *Buffer = (CHAR16 *)buf;
  EFI_FILE_HANDLE Handle;

  Status = Arg->Status;

  if (!EFI_ERROR (Status) && (Size > 0)) {
    if (Arg->Info->Attribute & EFI_FILE_DIRECTORY) {
      Print (L"=>Write Attribute(%x)\n", Arg->Info->Attribute);
      return Status;
    }

    Handle = Arg->Handle;

    Status  = Handle->Write (Handle, &Size, Buffer);
    Status  = Handle->Flush (Handle);
  }
  return Status;
}

int fwrite(
    const void *buf,
    unsigned long elsize,
    unsigned long  nelem,
    FILE *ptr_file_list
) {
    EFI_STATUS             Status = EFI_SUCCESS;
    EFI_LIST_ENTRY       *Link;
    SHELL_FILE_ARG      *Arg;
    UINTN                      Index;
    BOOLEAN                 IsSameFile;
   
    IsSameFile = FALSE;
    for (Link = ptr_file_list->Flink; Link != ptr_file_list && SI->RedirArgc; Link = Link->Flink) {
        BREAK_LOOP_ON_ESC ();
        Arg         = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
        IsSameFile  = FALSE;
        for (Index = 1; Index < SI->RedirArgc; Index += 2) {
            if (!EFI_ERROR (LibCompareFile (Arg->FullName, SI->RedirArgv[Index], &IsSameFile)) && IsSameFile) {
                break;
            }
        }

        if (IsSameFile) {
            break;
        }
    }

    if (!IsSameFile) {
        for (Link = ptr_file_list->Flink; Link != ptr_file_list; Link = Link->Flink) {
            BREAK_LOOP_ON_ESC ();
            Arg     = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
            Status = test_WriteFile (Arg, buf, (UINTN)(elsize * nelem));
        }
    } else {
        Status = EFI_REDIRECTION_SAME;
    }

    return (!EFI_ERROR (Status)) ? 0 : -1;
}
/*************************************************************************/
EFI_STATUS
test_ReadFile (
    SHELL_FILE_ARG  *Arg,
    const void *buf,
    UINTN Size
  )
{
  EFI_STATUS      Status;
  CHAR16          *Buffer = (CHAR16 *)buf;
  EFI_FILE_HANDLE Handle;

  Status = Arg->Status;

  if (!EFI_ERROR (Status) && (Size > 0)) {
    if (Arg->Info->Attribute & EFI_FILE_DIRECTORY) {
      Print (L"=>Read Attribute(%x)\n", Arg->Info->Attribute);
      return Status;
    }

    Handle = Arg->Handle;

    Status  = Handle->Read (Handle, &Size, Buffer);
  }
  return Status;
}

int fread(
    const void *buf,
    unsigned long elsize,
    unsigned long  nelem,
    FILE *ptr_file_list
) {
    EFI_STATUS             Status = EFI_SUCCESS;
    EFI_LIST_ENTRY       *Link;
    SHELL_FILE_ARG      *Arg;
    UINTN                      Index;
    BOOLEAN                 IsSameFile;
   
    IsSameFile = FALSE;
    for (Link = ptr_file_list->Flink; Link != ptr_file_list && SI->RedirArgc; Link = Link->Flink) {
        BREAK_LOOP_ON_ESC ();
        Arg         = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
        IsSameFile  = FALSE;
        for (Index = 1; Index < SI->RedirArgc; Index += 2) {
            if (!EFI_ERROR (LibCompareFile (Arg->FullName, SI->RedirArgv[Index], &IsSameFile)) && IsSameFile) {
                break;
            }
        }

        if (IsSameFile) {
            break;
        }
    }

    if (!IsSameFile) {
        for (Link = ptr_file_list->Flink; Link != ptr_file_list; Link = Link->Flink) {
            BREAK_LOOP_ON_ESC ();
            Arg     = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
            Status = test_ReadFile (Arg, buf, (UINTN)(elsize * nelem));
        }
    } else {
        Status = EFI_REDIRECTION_SAME;
    }

    return (!EFI_ERROR (Status)) ? 0 : -1;
}
/*************************************************************************/
long ftell(FILE *ptr_file_list)
{
    EFI_STATUS             Status = EFI_SUCCESS;
    EFI_LIST_ENTRY       *Link;
    SHELL_FILE_ARG      *Arg;
    UINTN                      Index;
    BOOLEAN                 IsSameFile;
    UINTN                      FileSize = 0;

    IsSameFile = FALSE;
    for (Link = ptr_file_list->Flink; Link != ptr_file_list && SI->RedirArgc; Link = Link->Flink) {
        BREAK_LOOP_ON_ESC ();
        Arg         = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
        IsSameFile  = FALSE;
        for (Index = 1; Index < SI->RedirArgc; Index += 2) {
            if (!EFI_ERROR (LibCompareFile (Arg->FullName, SI->RedirArgv[Index], &IsSameFile)) && IsSameFile) {
                break;
            }
        }

        if (IsSameFile) {
            break;
        }
    }

    if (!IsSameFile) {
        for (Link = ptr_file_list->Flink; Link != ptr_file_list; Link = Link->Flink) {
            BREAK_LOOP_ON_ESC ();
            Arg     = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
            Status = Arg->Status;
            if (!EFI_ERROR (Status)) {
                FileSize  = (UINTN) Arg->Info->FileSize;
            }
        }
    } else {
        Status = EFI_REDIRECTION_SAME;
    }

    return (long)FileSize;
}
/*************************************************************************/

int fputc(
    int c,
    FILE *ptr_file_list
) {
    EFI_STATUS             Status = EFI_SUCCESS;
    EFI_LIST_ENTRY       *Link;
    SHELL_FILE_ARG      *Arg;
    UINTN                      Index;
    BOOLEAN                 IsSameFile;

    //
    // Expand each arg and type each file
    //
    IsSameFile = FALSE;
    for (Link = ptr_file_list->Flink; Link != ptr_file_list && SI->RedirArgc; Link = Link->Flink) {
        BREAK_LOOP_ON_ESC ();
        Arg         = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
        IsSameFile  = FALSE;
        for (Index = 1; Index < SI->RedirArgc; Index += 2) {
            if (!EFI_ERROR (LibCompareFile (Arg->FullName, SI->RedirArgv[Index], &IsSameFile)) && IsSameFile) {
                break;
            }
        }

        if (IsSameFile) {
            break;
        }
    }

    if (!IsSameFile) {
        for (Link = ptr_file_list->Flink; Link != ptr_file_list; Link = Link->Flink) {
            BREAK_LOOP_ON_ESC ();
            Arg     = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
            Status = MV_WriteFile (Arg, (void *)&c, (UINTN)1);
        }
    } else {
        Status = EFI_REDIRECTION_SAME;
    }

    return (!EFI_ERROR (Status)) ? 0 : -1;
}
/*************************************************************************/
int fgetc(
    FILE *ptr_file_list
) {
    EFI_STATUS             Status = EFI_SUCCESS;
    EFI_LIST_ENTRY       *Link;
    SHELL_FILE_ARG      *Arg;
    UINTN                      Index;
    BOOLEAN                 IsSameFile;
    int c = -1;
    
    //
    // Expand each arg and type each file
    //
    IsSameFile = FALSE;
    for (Link = ptr_file_list->Flink; Link != ptr_file_list && SI->RedirArgc; Link = Link->Flink) {
        BREAK_LOOP_ON_ESC ();
        Arg         = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
        IsSameFile  = FALSE;
        for (Index = 1; Index < SI->RedirArgc; Index += 2) {
            if (!EFI_ERROR (LibCompareFile (Arg->FullName, SI->RedirArgv[Index], &IsSameFile)) && IsSameFile) {
                break;
            }
        }

        if (IsSameFile) {
            break;
        }
    }

    if (!IsSameFile) {
        for (Link = ptr_file_list->Flink; Link != ptr_file_list; Link = Link->Flink) {
            BREAK_LOOP_ON_ESC ();
            Arg     = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
            Status = MV_ReadFile (Arg, (void *)&c, (UINTN)1);
        }
    } else {
        Status = EFI_REDIRECTION_SAME;
    }

    return (!EFI_ERROR (Status)) ? c : -1;
}
/*************************************************************************/

STANDBY - E2h, Non-Data


STANDBY - E2h, Non-Data

Inputs:
Register
7
6
5
4
3
2
1
0
Features
Current
N/A
Previous
N/A
Sector Count
Current
This value shall determine the time period programmed into the Standby timer.
Previous
N/A
LBA Low
Current
N/A
Previous
N/A
LBA Mid
Current
N/A
Previous
N/A
LBA High
Current
N/A
Previous
N/A
Device
obs
N/A
obs
TD
Reserved
Command
E2h
Standby timer periods table
Count field
Description
00h
Standby time disabled
01h-F0h
(value * 5) seconds (i.e., 5 seconds to 1 200 seconds (i.e., 20
minutes))
F1h-FBh
((value - 240) * 30) minutes (i.e., 30 minutes to 330 minutes
(i.e., 5.5 hours))
FCh
21 minutes
FDh
Between 8 hours and 12 hours
FEh
Reserved
FFh
21 minutes 15 seconds
Note - Times are approximate.


Transport Dependent (TD): All bits and fields that are labeled transport dependent are defined in the transport standards.

Normal Outputs:
Register
7
6
5
4
3
2
1
0
Error
N/A
Sector Count
HOB = 0
N/A
HOB = 1
N/A
LBA Low
HOB = 0
N/A
HOB = 1
N/A
LBA Mid
HOB = 0
N/A
HOB = 1
N/A
LBA High
HOB = 0
N/A
HOB = 1
N/A
Device
obs
na
obs
TD
Reserved
Status
TD
DF
na
TD
na
na
ERR
Device Fault bit: If the device enters a condition where continued operation may affect user data integrity (e.g., failure to spin-up without error, or no spares remaining for reallocation), then the device shall set the Device Fault bit to one and no longer accept commands. This condition is only cleared by power cycling the device. Once the Device Fault bit has been cleared to zero it may remain clear until a command that affects user data integrity is received by the device.
Error bit: The Error bit shall be set to one if any bit in the Error field is set to one.

Error Outputs:
Register
7
6
5
4
3
2
1
0
Error
N/A
Sector Count
HOB = 0
N/A
HOB = 1
N/A
LBA Low
HOB = 0
N/A
HOB = 1
N/A
LBA Mid
HOB = 0
N/A
HOB = 1
N/A
LBA High
HOB = 0
N/A
HOB = 1
N/A
Device
obs
na
obs
TD
Reserved
Status
TD
DF
na
TD
na
sda
ERR
Sense Data Available:
The Sense Data Available bit shall be set to one if:
a)   IDENTIFY DEVICE data word 119 bit 6 is set to one;
b)   IDENTIFY DEVICE data word 120 bit 6 is set to one; and
c)   the device has sense data to report after processing any command.
The Sense Data Available bit is obsolete if:
a)   IDENTIFY DEVICE data word 119 bit 6 is cleared to zero; or
b)   IDENTIFY DEVICE data word 120 bit 6 is cleared to zero.