This tool manages the contents of BaseTools/Bin/<platform> by tracking which BaseTools binaries have been installed, and prompting the user to update their BaseTools when required.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jordan Justen <[email protected]> --- Source/C/BaseToolsBins/BaseToolsBins.c | 569 +++++++++++++++++++++++++++++++++ Source/C/BaseToolsBins/GNUmakefile | 22 ++ Source/C/BaseToolsBins/Makefile | 24 ++ Source/C/GNUmakefile | 1 + Source/C/Makefile | 1 + 5 files changed, 617 insertions(+) create mode 100644 Source/C/BaseToolsBins/BaseToolsBins.c create mode 100644 Source/C/BaseToolsBins/GNUmakefile create mode 100644 Source/C/BaseToolsBins/Makefile diff --git a/Source/C/BaseToolsBins/BaseToolsBins.c b/Source/C/BaseToolsBins/BaseToolsBins.c new file mode 100644 index 0000000..b82cff0 --- /dev/null +++ b/Source/C/BaseToolsBins/BaseToolsBins.c @@ -0,0 +1,569 @@ +/** @file + + Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include <Common/UefiBaseTypes.h> + +#include "CommonLib.h" +#include "MemoryFile.h" +#include "OsPath.h" +#include "EfiUtilityMsgs.h" + +// +// Include miniz code. It doesn't have a separate .h. +// +#include "miniz.c" + +#define UTILITY_NAME "BaseToolsBins" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +// +// Global variables +// +CHAR8 *InstallDir = NULL; +CHAR8 *ZipName = NULL; +CHAR8 *ZipUrl = NULL; +CHAR8 *InstalledZipName = NULL; + + +// +// BaseToolsBins functions +// + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Error / Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + + +STATIC +EFI_STATUS +GetInstallDir ( + CONST CHAR8* Executable + ) +{ + CONST CHAR8 Seps[] = "/\\"; + UINTN Loop; + UINTN PathLength; + + PathLength = 0; + + for (Loop = 0; Loop < ARRAY_SIZE (Seps) - 1; Loop++) { + CHAR8 Sep = Seps[Loop]; + CHAR8 *Loc; + + Loc = strrchr(Executable, Sep); + if (Loc != NULL) { + PathLength = MAX (PathLength, (UINTN) ((Loc + 1) - Executable)); + } + } + + if (PathLength > 0) { + InstallDir = malloc (PathLength + 1); + if (InstallDir == NULL) { + return EFI_OUT_OF_RESOURCES; + } + strncpy (InstallDir, Executable, PathLength); + InstallDir[PathLength] = (CHAR8) 0; + } else { + InstallDir = ""; + } + + return EFI_SUCCESS; +} + + +STATIC +CHAR8* +InstallDirAppend ( + CONST CHAR8* Suffix + ) +{ + UINTN PathLength; + CHAR8 *Result; + + PathLength = strlen (InstallDir) + strlen (Suffix); + Result = malloc (PathLength + 1); + + strcpy (Result, InstallDir); + strcat (Result, Suffix); + + return Result; +} + + +STATIC +BOOLEAN +StartsWith ( + CONST CHAR8* String, + CONST CHAR8* Prefix + ) +{ + if (String == NULL || Prefix == NULL) { + return FALSE; + } + + if (strncmp(String, Prefix, strlen(Prefix)) == 0) { + return TRUE; + } + + return FALSE; +} + + +STATIC +CHAR8* +StrRStrip ( + CHAR8* String + ) +{ + UINTN Offset; + + if (String == NULL) { + return NULL; + } + + Offset = strlen (String); + + do { + if (Offset == 0) { + return String; + } + Offset--; + if (!isspace(String[Offset])) { + break; + } + + String[Offset] = (CHAR8) 0; + } while (TRUE); + + return String; +} + + +STATIC +CHAR8* +GetIniStringValue ( + CONST CHAR8 *IniLine + ) +{ + CHAR8 *Result; + CHAR8 *Loc; + UINTN ResultLength; + + Loc = strchr (IniLine, ':'); + if (Loc == NULL) { + return NULL; + } + + Loc++; + + while (*Loc == ' ') { + Loc++; + } + + ResultLength = strlen(Loc); + Result = malloc(ResultLength + 1); + if (Result == NULL) { + return NULL; + } + + strcpy (Result, Loc); + StrRStrip (Result); + + return Result; +} + + +STATIC +EFI_STATUS +ParseIni ( + BOOLEAN VersionIni + ) +{ + EFI_STATUS Status; + EFI_HANDLE File; + CHAR8 *IniFileName; + CHAR8 *Line; + BOOLEAN FoundSection; + + IniFileName = InstallDirAppend (VersionIni ? "version.ini" : "installed.ini"); + + if (!OsPathExists (IniFileName)) { + CHAR8 *ErrorStr; + + if (!VersionIni) { + // + // If we are loading installed.ini, then it is okay if it doesn't exist, + // and we don't need to print an error message. + // + free (IniFileName); + return EFI_NOT_FOUND; + } + + ErrorStr = malloc (strlen (IniFileName) + 80); + if (ErrorStr) { + sprintf (ErrorStr, "file %s not found", IniFileName); + Error (NULL, 0, 4001, UTILITY_NAME, ErrorStr); + free (ErrorStr); + } else { + Error (NULL, 0, 4001, UTILITY_NAME, "INI file not found"); + } + + free (IniFileName); + return EFI_NOT_FOUND; + } + + Status = GetMemoryFile (IniFileName, &File); + if (EFI_ERROR (Status)) { + return Status; + } + + FoundSection = FALSE; + do { + Line = ReadMemoryFileLine (File); + if (Line == NULL) { + break; + } + + if (strcmp (Line, "[zip]") == 0) { + FoundSection = TRUE; + free (Line); + break; + } + + free (Line); + } while (TRUE); + + if (!FoundSection) { + FreeMemoryFile (File); + return EFI_NOT_FOUND; + } + + do { + Line = ReadMemoryFileLine (File); + if (Line == NULL) { + break; + } + + if (Line[0] == '[') { + free (Line); + break; + } + + if (StartsWith (Line, "file:")) { + CHAR8 *Value = GetIniStringValue (Line); + if (VersionIni) { + ZipName = Value; + } else { + InstalledZipName = Value; + } + } else if (VersionIni && StartsWith (Line, "url:")) { + ZipUrl = GetIniStringValue (Line); + } + + free (Line); + } while (TRUE); + + if (ZipName == NULL) { + Error (NULL, 0, 4001, UTILITY_NAME, "zip filename not found"); + } + + FreeMemoryFile (File); + return Status; +} + + +STATIC +EFI_STATUS +InstallBaseToolsFiles ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE ZipMemoryFile; + mz_zip_archive ZipFile; + mz_bool MzBool; + UINTN NumFiles; + UINTN FileNum; + CHAR8 *ZipFullPath; + + ZipFullPath = InstallDirAppend (ZipName); + if (ZipFullPath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (!OsPathExists (ZipFullPath)) { + printf ("Unable to open %s\n", ZipFullPath); + printf ("You can download this BaseTools bin release at:\n%s\n", ZipUrl); + free (ZipFullPath); + return EFI_NOT_FOUND; + } + + Status = GetMemoryFile (ZipFullPath, &ZipMemoryFile); + if (EFI_ERROR (Status)) { + free (ZipFullPath); + return Status; + } + + ZeroMem (&ZipFile, sizeof (ZipFile)); + + MzBool = mz_zip_reader_init_mem( + &ZipFile, + GetMemoryFileContents (ZipMemoryFile), + GetMemoryFileSize (ZipMemoryFile), + 0); + if (!MzBool) { + Error (NULL, 0, 4001, UTILITY_NAME, "failed to open zip file"); + Status = EFI_VOLUME_CORRUPTED; + goto FreeMemoryFile; + } + + NumFiles = mz_zip_reader_get_num_files(&ZipFile); + printf("Zip num files: %d\n", (int) NumFiles); + + for (FileNum = 0; FileNum < NumFiles; FileNum++) { + CHAR8 *ArchiveName; + CHAR8 *DestName; + UINTN ArchiveNameLength; + + ArchiveNameLength = mz_zip_reader_get_filename ( + &ZipFile, + FileNum, + NULL, + 0 + ); + + ArchiveName = malloc (ArchiveNameLength); + if (ArchiveName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeZipFile; + } + + mz_zip_reader_get_filename ( + &ZipFile, + FileNum, + ArchiveName, + ArchiveNameLength + ); + + printf("Zip archive name: %s\n", ArchiveName); + + DestName = InstallDirAppend (ArchiveName); + free (ArchiveName); + + MzBool = mz_zip_reader_extract_to_file ( + &ZipFile, + FileNum, + DestName, + 0 + ); + if (!MzBool) { + Error (NULL, 0, 4001, UTILITY_NAME, "failed extract zip archive file"); + Status = EFI_VOLUME_CORRUPTED; + goto FreeZipFile; + } + } + + Status = EFI_SUCCESS; + +FreeZipFile: + mz_zip_reader_end(&ZipFile); + +FreeMemoryFile: + FreeMemoryFile (ZipMemoryFile); + free (ZipFullPath); + + return Status; +} + + +STATIC +EFI_STATUS +WriteInstalledIni ( + VOID + ) +{ + CHAR8 *IniFullPath; + FILE *Ini; + + IniFullPath = InstallDirAppend ("installed.ini"); + if (IniFullPath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ini = fopen (IniFullPath, "wb"); + if (Ini == NULL) { + free (IniFullPath); + Error (NULL, 0, 4001, UTILITY_NAME, "failed to open installed.ini file"); + return EFI_WRITE_PROTECTED; + } + + fprintf (Ini, "[zip]\n"); + fprintf (Ini, "file: %s\n", ZipName); + + fclose (Ini); + free (IniFullPath); + return EFI_SUCCESS; +} + + +/** + Main function. + + @param argc Number of command line parameters. + @param argv Array of pointers to command line parameter strings. + + @retval STATUS_SUCCESS Utility exits successfully. + @retval STATUS_ERROR Some error occurred during execution. + +**/ +int +main ( + int argc, + char *argv[] + ) +{ + EFI_STATUS Status; + + Status = GetInstallDir (argv[0]); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + + // + // Parse command line + // + argc --; + argv ++; + + if (argc > 0 && ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0))) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (argc > 0 && stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + // + // Parse version.ini file + // + Status = ParseIni (TRUE); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + + // + // Parse installed.ini file + // + Status = ParseIni (FALSE); + + // + // If installed.ini exists, then check to see if the BaseTools binaries + // have already been installed. + // + if (!EFI_ERROR (Status)) { + if (strcmp (ZipName, InstalledZipName) == 0) { + // + // The BaseTools binaries are already installed, so we can exit now + // + return STATUS_SUCCESS; + } + } + + // + // Unzip the archive with the BaseTools binaries + // + Status = InstallBaseToolsFiles (); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + + Status = WriteInstalledIni (); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 4001, UTILITY_NAME, "WriteInstalledIni failed"); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} diff --git a/Source/C/BaseToolsBins/GNUmakefile b/Source/C/BaseToolsBins/GNUmakefile new file mode 100644 index 0000000..eae69c2 --- /dev/null +++ b/Source/C/BaseToolsBins/GNUmakefile @@ -0,0 +1,22 @@ +## @file +# GNU/Linux makefile for 'BaseToolsBins' module build. +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR> +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = BaseToolsBins + +OBJECTS = BaseToolsBins.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon diff --git a/Source/C/BaseToolsBins/Makefile b/Source/C/BaseToolsBins/Makefile new file mode 100644 index 0000000..24ca5be --- /dev/null +++ b/Source/C/BaseToolsBins/Makefile @@ -0,0 +1,24 @@ +## @file +# Windows makefile for 'BaseToolsBins' module build. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = BaseToolsBins + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = BaseToolsBins.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/Source/C/GNUmakefile b/Source/C/GNUmakefile index 124517b..75a2ae5 100644 --- a/Source/C/GNUmakefile +++ b/Source/C/GNUmakefile @@ -44,6 +44,7 @@ all: makerootdir subdirs $(MAKEROOT)/libs LIBRARIES = Common # NON_BUILDABLE_APPLICATIONS = GenBootSector BootSectImage APPLICATIONS = \ + BaseToolsBins \ GnuGenBootSector \ BootSectImage \ EfiLdrImage \ diff --git a/Source/C/Makefile b/Source/C/Makefile index bf3cfb4..cc7f077 100644 --- a/Source/C/Makefile +++ b/Source/C/Makefile @@ -16,6 +16,7 @@ ARCH = IA32 LIBRARIES = Common APPLICATIONS = \ + BaseToolsBins \ BootSectImage \ EfiLdrImage \ EfiRom \ -- 1.9.2 ------------------------------------------------------------------------------ Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce _______________________________________________ edk2-buildtools-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/edk2-buildtools-devel
