/*++ Copyright (c) 2014 Minoca Corp. All Rights Reserved Module Name: plat.c Abstract: This module contains platform specific setup instructions. Author: Evan Green 7-May-2014 Environment: User Mode --*/ // // ------------------------------------------------------------------- Includes // #include #include #include #include #include #include #include #include "setup.h" // // ---------------------------------------------------------------- Definitions // #define SETUP_RECIPE_FLAG_HIDDEN 0x00000001 // // ------------------------------------------------------ Data Type Definitions // /*++ Structure Description: This structure stores installation directions for a specific platform or configuration. Members: Id - Stores the recipe identifier. ShortName - Stores the short name of the platform, usually used at the command line. Description - Stores the longer name of the platform, used when printing. SmbiosProductName - Stores the platform name in the SMBIOS product name field. Flags - Stores a bitfield of flags. See SETUP_RECIPE_FLAG_* definitions. Script - Stores a pointer to the script corresponding to this recipe. ScriptEnd - Stores the pointer to the end of the script (the first invalid character). It's assumed there is no null terminator. --*/ typedef struct _SETUP_RECIPE { SETUP_RECIPE_ID Id; PSTR ShortName; PSTR Description; PSTR SmbiosProductName; ULONG Flags; PVOID Script; PVOID ScriptEnd; } SETUP_RECIPE, *PSETUP_RECIPE; // // ----------------------------------------------- Internal Function Prototypes // // // -------------------------------------------------------------------- Globals // // // The objcopy utility provides symbols for the start, size, and end of the // text files converted to object files. These correspond directly to the // file names in the config directory, and are alphabetized. // extern PVOID _binary_bbone_txt_start; extern PVOID _binary_bbone_txt_end; extern PVOID _binary_common_txt_start; extern PVOID _binary_common_txt_end; extern PVOID _binary_galileo_txt_start; extern PVOID _binary_galileo_txt_end; extern PVOID _binary_instarv6_txt_start; extern PVOID _binary_instarv6_txt_end; extern PVOID _binary_instarv7_txt_start; extern PVOID _binary_instarv7_txt_end; extern PVOID _binary_instx86_txt_start; extern PVOID _binary_instx86_txt_end; extern PVOID _binary_integrd_txt_start; extern PVOID _binary_integrd_txt_end; extern PVOID _binary_panda_txt_start; extern PVOID _binary_panda_txt_end; extern PVOID _binary_pandausb_txt_start; extern PVOID _binary_pandausb_txt_end; extern PVOID _binary_pc_txt_start; extern PVOID _binary_pc_txt_end; extern PVOID _binary_pcefi_txt_start; extern PVOID _binary_pcefi_txt_end; extern PVOID _binary_pctiny_txt_start; extern PVOID _binary_pctiny_txt_end; extern PVOID _binary_rpi2_txt_start; extern PVOID _binary_rpi2_txt_end; extern PVOID _binary_rpi_txt_start; extern PVOID _binary_rpi_txt_end; extern PVOID _binary_veyron_txt_start; extern PVOID _binary_veyron_txt_end; // // Define the recipes used to install to specific platforms. These are kept // in the same order as above. // SETUP_RECIPE SetupRecipes[] = { { SetupRecipeNone, "None", "Complete user customization", NULL, SETUP_RECIPE_FLAG_HIDDEN, NULL, NULL }, { SetupRecipeBeagleBoneBlack, "beagleboneblack", "TI BeagleBone Black", "A335BNLT", 0, &_binary_bbone_txt_start, &_binary_bbone_txt_end }, { SetupRecipeCommon, "common", "Common initialization", NULL, SETUP_RECIPE_FLAG_HIDDEN, &_binary_common_txt_start, &_binary_common_txt_end }, { SetupRecipeGalileo, "galileo", "Intel Galileo", "QUARK", 0, &_binary_galileo_txt_start, &_binary_galileo_txt_end }, { SetupRecipeInstallArmv6, "install-armv6", "ARMv6 Install Image Recipe", NULL, SETUP_RECIPE_FLAG_HIDDEN, &_binary_instarv6_txt_start, &_binary_instarv6_txt_end }, { SetupRecipeInstallArmv7, "install-armv7", "ARMv7 Install Image Recipe", NULL, SETUP_RECIPE_FLAG_HIDDEN, &_binary_instarv7_txt_start, &_binary_instarv7_txt_end }, { SetupRecipeInstallX86, "install-x86", "x86 Install Image Recipe", NULL, SETUP_RECIPE_FLAG_HIDDEN, &_binary_instx86_txt_start, &_binary_instx86_txt_end }, { SetupRecipeIntegratorCpRamDisk, "integrd", "Integrator/CP RAM Disk Recipe", NULL, SETUP_RECIPE_FLAG_HIDDEN, &_binary_integrd_txt_start, &_binary_integrd_txt_end }, { SetupRecipePandaBoard, "panda", "TI PandaBoard", "PandaBoard", 0, &_binary_panda_txt_start, &_binary_panda_txt_end }, { SetupRecipePandaBoard, "panda-es", "TI PandaBoard ES", "PandaBoard ES", SETUP_RECIPE_FLAG_HIDDEN, &_binary_panda_txt_start, &_binary_panda_txt_end }, { SetupRecipePandaBoardUsb, "panda-usb", "TI PandaBoard USB Image Recipe", NULL, SETUP_RECIPE_FLAG_HIDDEN, &_binary_pandausb_txt_start, &_binary_pandausb_txt_end }, { SetupRecipePc, "pc", "Standard x86 BIOS PC", NULL, 0, &_binary_pc_txt_start, &_binary_pc_txt_end }, { SetupRecipePcEfi, "pcefi", "Standard x86 UEFI-based PC", NULL, 0, &_binary_pcefi_txt_start, &_binary_pcefi_txt_end }, { SetupRecipePcTiny, "pc-tiny", "Minimal PC installation for Qemu", NULL, SETUP_RECIPE_FLAG_HIDDEN, &_binary_pctiny_txt_start, &_binary_pctiny_txt_end }, { SetupRecipeRaspberryPi2, "raspberrypi2", "Raspberry Pi 2", "Raspberry Pi 2", 0, &_binary_rpi2_txt_start, &_binary_rpi2_txt_end }, { SetupRecipeRaspberryPi, "raspberrypi", "Raspberry Pi", "Raspberry Pi", 0, &_binary_rpi_txt_start, &_binary_rpi_txt_end }, { SetupRecipeVeyron, "veyron", "ASUS C201", "C201", 0, &_binary_veyron_txt_start, &_binary_veyron_txt_end }, }; // // ------------------------------------------------------------------ Functions // BOOL SetupParsePlatformString ( PSETUP_CONTEXT Context, PSTR PlatformString ) /*++ Routine Description: This routine converts a platform string into a platform identifier, and sets it in the setup context. Arguments: Context - Supplies a pointer to the setup context. PlatformString - Supplies a pointer to the string to convert to a platform identifier. Return Value: TRUE if the platform name was successfully converted. FALSE if the name was invalid. --*/ { PSETUP_RECIPE Recipe; ULONG RecipeCount; ULONG RecipeIndex; RecipeCount = sizeof(SetupRecipes) / sizeof(SetupRecipes[0]); for (RecipeIndex = 0; RecipeIndex < RecipeCount; RecipeIndex += 1) { Recipe = &(SetupRecipes[RecipeIndex]); if (((Recipe->ShortName != NULL) && (strcasecmp(PlatformString, Recipe->ShortName) == 0)) || ((Recipe->Description != NULL) && (strcasecmp(PlatformString, Recipe->Description) == 0))) { Context->RecipeIndex = RecipeIndex; return TRUE; } } return FALSE; } VOID SetupPrintPlatformList ( VOID ) /*++ Routine Description: This routine prints the supported platform list. Arguments: None. Return Value: None. --*/ { PSETUP_RECIPE Recipe; ULONG RecipeCount; ULONG RecipeIndex; printf("Supported platforms:\n"); RecipeCount = sizeof(SetupRecipes) / sizeof(SetupRecipes[0]); for (RecipeIndex = 0; RecipeIndex < RecipeCount; RecipeIndex += 1) { Recipe = &(SetupRecipes[RecipeIndex]); if ((Recipe->Flags & SETUP_RECIPE_FLAG_HIDDEN) != 0) { continue; } printf(" %s -- %s\n", Recipe->ShortName, Recipe->Description); } return; } INT SetupDeterminePlatform ( PSETUP_CONTEXT Context ) /*++ Routine Description: This routine finalizes the setup platform recipe to use. Arguments: Context - Supplies a pointer to the setup context. Return Value: 0 on success. Non-zero on failure. --*/ { SETUP_RECIPE_ID Fallback; LONG FallbackRecipeIndex; PSTR PlatformName; PSETUP_RECIPE Recipe; ULONG RecipeCount; ULONG RecipeIndex; INT Result; INT SmbiosLength; PSTR SmbiosName; PlatformName = NULL; Fallback = SetupRecipeNone; // // If the user specified a platform, just use it. // if (Context->RecipeIndex != -1) { return 0; } // // Ask the OS to detect the current platform. // Result = SetupOsGetPlatformName(&PlatformName, &Fallback); if (Result != 0) { if (Result != ENOSYS) { fprintf(stderr, "Failed to detect platform: %s\n", strerror(Result)); } goto DeterminePlatformEnd; } if ((Context->Flags & SETUP_FLAG_VERBOSE) != 0) { printf("SMBIOS Platform Name: %s\n", PlatformName); } FallbackRecipeIndex = -1; RecipeCount = sizeof(SetupRecipes) / sizeof(SetupRecipes[0]); for (RecipeIndex = 0; RecipeIndex < RecipeCount; RecipeIndex += 1) { Recipe = &(SetupRecipes[RecipeIndex]); if (Recipe->Id == Fallback) { FallbackRecipeIndex = RecipeIndex; } // // Compare the name, ignoring case and ignoring any extra stuff that // might be on the end like a version. // SmbiosName = Recipe->SmbiosProductName; if ((PlatformName != NULL) && (SmbiosName != NULL)) { SmbiosLength = strlen(SmbiosName); if (strncasecmp(SmbiosName, PlatformName, SmbiosLength) == 0) { Context->RecipeIndex = RecipeIndex; break; } } } if (Context->RecipeIndex == -1) { if (FallbackRecipeIndex == -1) { fprintf(stderr, "Failed to convert platform name %s to recipe.\n", PlatformName); Result = EINVAL; goto DeterminePlatformEnd; } Context->RecipeIndex = FallbackRecipeIndex; } if ((Context->Flags & SETUP_FLAG_VERBOSE) != 0) { Recipe = &(SetupRecipes[Context->RecipeIndex]); printf("Platform: %s\n", Recipe->Description); } Result = 0; DeterminePlatformEnd: if (PlatformName != NULL) { free(PlatformName); } return Result; } INT SetupAddRecipeScript ( PSETUP_CONTEXT Context ) /*++ Routine Description: This routine adds the platform recipe script. Arguments: Context - Supplies a pointer to the setup context. Return Value: 0 on success. Non-zero on failure. --*/ { PSETUP_RECIPE Recipe; UINTN ScriptSize; INT Status; if (Context->RecipeIndex == -1) { return 0; } Recipe = &(SetupRecipes[Context->RecipeIndex]); if (Recipe->Script == NULL) { return 0; } ScriptSize = (UINTN)(Recipe->ScriptEnd) - (UINTN)(Recipe->Script); Status = ChalkLoadScriptBuffer(&(Context->Interpreter), Recipe->ShortName, Recipe->Script, ScriptSize, 0, NULL); return Status; } INT SetupAddCommonScripts ( PSETUP_CONTEXT Context ) /*++ Routine Description: This routine adds the common scripts that are added no matter what. Arguments: Context - Supplies a pointer to the setup context. Return Value: 0 on success. Non-zero on failure. --*/ { PSETUP_RECIPE Recipe; ULONG RecipeCount; ULONG RecipeIndex; UINTN ScriptSize; INT Status; Status = 0; RecipeCount = sizeof(SetupRecipes) / sizeof(SetupRecipes[0]); for (RecipeIndex = 0; RecipeIndex < RecipeCount; RecipeIndex += 1) { Recipe = &(SetupRecipes[RecipeIndex]); if (Recipe->Id != SetupRecipeCommon) { continue; } ScriptSize = (UINTN)(Recipe->ScriptEnd) - (UINTN)(Recipe->Script); Status = ChalkLoadScriptBuffer(&(Context->Interpreter), Recipe->ShortName, Recipe->Script, ScriptSize, 0, NULL); if (Status != 0) { fprintf(stderr, "Failed to add common scripts.\n"); break; } } return Status; } // // --------------------------------------------------------- Internal Functions //