VOID Flash_Start_OS ( ) { UINT32 Index = 0; UINTN FDTConfigTable = 0; EFI_STATUS Status; ESL_LINUX LinuxKernel = (ESL_LINUX)(0x80000); if (!PcdGet32(PcdIsMPBoot)) { for (Index = 0; Index < gST->NumberOfTableEntries; Index ++) { if (CompareGuid (&gFdtTableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) { FDTConfigTable = (UINTN)gST->ConfigurationTable[Index].VendorTable; DEBUG ((EFI_D_ERROR, "FDTConfigTable Address: 0x%lx\n",FDTConfigTable)); break; } } gBS->CopyMem((void *)0x6000000,(void *)FDTConfigTable,0x100000); MicroSecondDelay(20000); gBS->CopyMem((void *)LinuxKernel,(void *)0x90100000,0x1F00000); MicroSecondDelay(200000); gBS->CopyMem((void *)0x7000000,(void *)0x92000000,0x4000000); MicroSecondDelay(200000); DEBUG((EFI_D_ERROR,"Update FDT\n")); Status = EFIFdtUpdate(0x06000000); if(EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR,"EFIFdtUpdate ERROR\n")); goto Exit; } } else { Status = LzmaDecompressKernel (LinuxKernel); if(EFI_ERROR(Status)) { goto Exit; } gBS->CopyMem((void *)0x6000000, (void *)0xA47C0000, 0x20000); MicroSecondDelay(20000); gBS->CopyMem((void *)0x7000000, (void *)0xA4000000, 0x7C0000); MicroSecondDelay(200000); } Status = ShutdownUefiBootServices (); if(EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status)); goto Exit; } // // Switch off interrupts, caches, mmu, etc // Status = PreparePlatformHardware (); ASSERT_EFI_ERROR(Status); LinuxKernel (0x06000000,0,0,0); // Kernel should never exit // After Life services are not provided ASSERT(FALSE); Exit: // Only be here if we fail to start Linux Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status); // Free Runtimee Memory (kernel and FDT) return ; }
VOID ESL_Start_OS ( ) { EFI_STATUS Status; UINTN Reg_Value; ESL_LINUX LinuxKernel = (ESL_LINUX)(0x80000); if(!PcdGet32(PcdIsMPBoot)) { DEBUG((EFI_D_ERROR,"Update FDT\n")); Status = EFIFdtUpdate(0x06000000); if(EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR,"EFIFdtUpdate ERROR\n")); goto Exit; } } DEBUG((EFI_D_ERROR, "[%a]:[%dL] Start to boot Linux\n", __FUNCTION__, __LINE__)); SmmuConfigForLinux(); ITSCONFIG(); if(PcdGet32(PcdIsMPBoot)) { *(volatile UINT32 *)(0x60016220) = 0x7; *(volatile UINT32 *)(0x60016230) = 0x40016260; *(volatile UINT32 *)(0x60016234) = 0X0; *(volatile UINT32 *)(0x60016238) = 0x60016260; *(volatile UINT32 *)(0x6001623C) = 0x400; *(volatile UINT32 *)(0x60016240) = 0x40016260; *(volatile UINT32 *)(0x60016244) = 0x400; *(volatile UINT32 *)(0x40016220) = 0x7; *(volatile UINT32 *)(0x40016230) = 0x60016260; *(volatile UINT32 *)(0x40016234) = 0X0; *(volatile UINT32 *)(0x40016238) = 0x60016260; *(volatile UINT32 *)(0x4001623C) = 0x400; *(volatile UINT32 *)(0x40016240) = 0x40016260; *(volatile UINT32 *)(0x40016244) = 0x400; *(volatile UINT32 *)(0x60016220 + S1_BASE) = 0x7; *(volatile UINT32 *)(0x60016230 + S1_BASE) = 0x40016260; *(volatile UINT32 *)(0x60016234 + S1_BASE) = 0X0; *(volatile UINT32 *)(0x60016238 + S1_BASE) = 0x60016260; *(volatile UINT32 *)(0x6001623C + S1_BASE) = 0x0; *(volatile UINT32 *)(0x60016240 + S1_BASE) = 0x40016260; *(volatile UINT32 *)(0x60016244 + S1_BASE) = 0x400; *(volatile UINT32 *)(0x40016220 + S1_BASE) = 0x7; *(volatile UINT32 *)(0x40016230 + S1_BASE) = 0x60016260; *(volatile UINT32 *)(0x40016234 + S1_BASE) = 0X0; *(volatile UINT32 *)(0x40016238 + S1_BASE) = 0x60016260; *(volatile UINT32 *)(0x4001623C + S1_BASE) = 0x400; *(volatile UINT32 *)(0x40016240 + S1_BASE) = 0x40016260; *(volatile UINT32 *)(0x40016244 + S1_BASE) = 0x0; } Status = ShutdownUefiBootServices (); if(EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status)); goto Exit; } // // Switch off interrupts, caches, mmu, etc // Status = PreparePlatformHardware (); ASSERT_EFI_ERROR(Status); *(volatile UINT32*)0xFFF8 = 0x0; *(volatile UINT32*)0xFFFC = 0x0; asm("DSB SY"); asm("ISB"); if (!PcdGet64 (PcdTrustedFirmwareEnable)) { StartupAp(); } Reg_Value = asm_read_reg(); DEBUG((EFI_D_ERROR,"CPUECTLR_EL1 = 0x%llx\n",Reg_Value)); MN_CONFIG (); DEBUG((EFI_D_ERROR, "[%a]:[%dL] Start to jump Linux kernel\n", __FUNCTION__, __LINE__)); LinuxKernel (0x06000000,0,0,0); // Kernel should never exit // After Life services are not provided ASSERT(FALSE); Exit: // Only be here if we fail to start Linux Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status); // Free Runtimee Memory (kernel and FDT) return ; }
STATIC EFI_STATUS StartLinux ( IN EFI_PHYSICAL_ADDRESS LinuxImage, IN UINTN LinuxImageSize, IN EFI_PHYSICAL_ADDRESS KernelParamsAddress, IN UINTN KernelParamsSize, IN UINT32 MachineType ) { EFI_STATUS Status; LINUX_KERNEL LinuxKernel; // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event. Status = ShutdownUefiBootServices (); if(EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status)); goto Exit; } // Move the kernel parameters to any address inside the first 1MB. // This is necessary because the ARM Linux kernel requires // the FTD / ATAG List to reside entirely inside the first 1MB of // physical memory. //Note: There is no requirement on the alignment if (MachineType != ARM_FDT_MACHINE_TYPE) { if (((UINTN)KernelParamsAddress > LINUX_ATAG_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxAtagMaxOffset))) { KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_ATAG_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize); } } else { if (((UINTN)KernelParamsAddress > LINUX_FDT_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxFdtMaxOffset))) { KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_FDT_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize); } } if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) { //Note: There is no requirement on the alignment LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize); } else { LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage; } // Check if the Linux Image is a uImage if (*(UINT32*)LinuxKernel == LINUX_UIMAGE_SIGNATURE) { // Assume the Image Entry Point is just after the uImage header (64-byte size) LinuxKernel = (LINUX_KERNEL)((UINTN)LinuxKernel + 64); LinuxImageSize -= 64; } // Check there is no overlapping between kernel and its parameters // We can only assert because it is too late to fallback to UEFI (ExitBootServices has been called). ASSERT (!IS_ADDRESS_IN_REGION(LinuxKernel, LinuxImageSize, KernelParamsAddress) && !IS_ADDRESS_IN_REGION(LinuxKernel, LinuxImageSize, KernelParamsAddress + KernelParamsSize)); // // Switch off interrupts, caches, mmu, etc // Status = PreparePlatformHardware (); ASSERT_EFI_ERROR(Status); // Register and print out performance information PERF_END (NULL, "BDS", NULL, 0); if (PerformanceMeasurementEnabled ()) { PrintPerformance (); } // // Start the Linux Kernel // // Outside BootServices, so can't use Print(); DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n")); // Jump to kernel with register set LinuxKernel ((UINTN)0, MachineType, (UINTN)KernelParamsAddress); // Kernel should never exit // After Life services are not provided ASSERT(FALSE); Exit: // Only be here if we fail to start Linux Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status); // Free Runtimee Memory (kernel and FDT) return Status; }