• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 
3   Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
4   This program and the accompanying materials
5   are licensed and made available under the terms and conditions of the BSD License
6   which accompanies this distribution.  The full text of the license may be found at
7   http://opensource.org/licenses/bsd-license.php
8 
9   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 **/
13 
14 #include <Uefi.h>
15 
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/LoadLinuxLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/QemuFwCfgLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiLib.h>
23 
24 
25 EFI_STATUS
TryRunningQemuKernel(VOID)26 TryRunningQemuKernel (
27   VOID
28   )
29 {
30   EFI_STATUS                Status;
31   UINTN                     KernelSize;
32   UINTN                     KernelInitialSize;
33   VOID                      *KernelBuf;
34   UINTN                     SetupSize;
35   VOID                      *SetupBuf;
36   UINTN                     CommandLineSize;
37   CHAR8                     *CommandLine;
38   UINTN                     InitrdSize;
39   VOID*                     InitrdData;
40 
41   SetupBuf = NULL;
42   SetupSize = 0;
43   KernelBuf = NULL;
44   KernelInitialSize = 0;
45   CommandLine = NULL;
46   CommandLineSize = 0;
47   InitrdData = NULL;
48   InitrdSize = 0;
49 
50   if (!QemuFwCfgIsAvailable ()) {
51     return EFI_NOT_FOUND;
52   }
53 
54   QemuFwCfgSelectItem (QemuFwCfgItemKernelSize);
55   KernelSize = (UINTN) QemuFwCfgRead64 ();
56 
57   QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize);
58   SetupSize = (UINTN) QemuFwCfgRead64 ();
59 
60   if (KernelSize == 0 || SetupSize == 0) {
61     DEBUG ((EFI_D_INFO, "qemu -kernel was not used.\n"));
62     return EFI_NOT_FOUND;
63   }
64 
65   SetupBuf = LoadLinuxAllocateKernelSetupPages (EFI_SIZE_TO_PAGES (SetupSize));
66   if (SetupBuf == NULL) {
67     DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel setup!\n"));
68     return EFI_OUT_OF_RESOURCES;
69   }
70 
71   DEBUG ((EFI_D_INFO, "Setup size: 0x%x\n", (UINT32) SetupSize));
72   DEBUG ((EFI_D_INFO, "Reading kernel setup image ..."));
73   QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData);
74   QemuFwCfgReadBytes (SetupSize, SetupBuf);
75   DEBUG ((EFI_D_INFO, " [done]\n"));
76 
77   Status = LoadLinuxCheckKernelSetup (SetupBuf, SetupSize);
78   if (EFI_ERROR (Status)) {
79     goto FreeAndReturn;
80   }
81 
82   Status = LoadLinuxInitializeKernelSetup (SetupBuf);
83   if (EFI_ERROR (Status)) {
84     goto FreeAndReturn;
85   }
86 
87   KernelInitialSize = LoadLinuxGetKernelSize (SetupBuf, KernelSize);
88   if (KernelInitialSize == 0) {
89     Status = EFI_UNSUPPORTED;
90     goto FreeAndReturn;
91   }
92 
93   KernelBuf = LoadLinuxAllocateKernelPages (
94                 SetupBuf,
95                 EFI_SIZE_TO_PAGES (KernelInitialSize));
96   if (KernelBuf == NULL) {
97     DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel!\n"));
98     Status = EFI_OUT_OF_RESOURCES;
99     goto FreeAndReturn;
100   }
101 
102   DEBUG ((EFI_D_INFO, "Kernel size: 0x%x\n", (UINT32) KernelSize));
103   DEBUG ((EFI_D_INFO, "Reading kernel image ..."));
104   QemuFwCfgSelectItem (QemuFwCfgItemKernelData);
105   QemuFwCfgReadBytes (KernelSize, KernelBuf);
106   DEBUG ((EFI_D_INFO, " [done]\n"));
107 
108   QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize);
109   CommandLineSize = (UINTN) QemuFwCfgRead64 ();
110 
111   if (CommandLineSize > 0) {
112     CommandLine = LoadLinuxAllocateCommandLinePages (
113                     EFI_SIZE_TO_PAGES (CommandLineSize));
114     QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);
115     QemuFwCfgReadBytes (CommandLineSize, CommandLine);
116   } else {
117     CommandLine = NULL;
118   }
119 
120   Status = LoadLinuxSetCommandLine (SetupBuf, CommandLine);
121   if (EFI_ERROR (Status)) {
122     goto FreeAndReturn;
123   }
124 
125   QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize);
126   InitrdSize = (UINTN) QemuFwCfgRead64 ();
127 
128   if (InitrdSize > 0) {
129     InitrdData = LoadLinuxAllocateInitrdPages (
130                    SetupBuf,
131                    EFI_SIZE_TO_PAGES (InitrdSize)
132                    );
133     DEBUG ((EFI_D_INFO, "Initrd size: 0x%x\n", (UINT32) InitrdSize));
134     DEBUG ((EFI_D_INFO, "Reading initrd image ..."));
135     QemuFwCfgSelectItem (QemuFwCfgItemInitrdData);
136     QemuFwCfgReadBytes (InitrdSize, InitrdData);
137     DEBUG ((EFI_D_INFO, " [done]\n"));
138   } else {
139     InitrdData = NULL;
140   }
141 
142   Status = LoadLinuxSetInitrd (SetupBuf, InitrdData, InitrdSize);
143   if (EFI_ERROR (Status)) {
144     goto FreeAndReturn;
145   }
146 
147   //
148   // Signal the EVT_SIGNAL_READY_TO_BOOT event
149   //
150   EfiSignalEventReadyToBoot();
151 
152   Status = LoadLinux (KernelBuf, SetupBuf);
153 
154 FreeAndReturn:
155   if (SetupBuf != NULL) {
156     FreePages (SetupBuf, EFI_SIZE_TO_PAGES (SetupSize));
157   }
158   if (KernelBuf != NULL) {
159     FreePages (KernelBuf, EFI_SIZE_TO_PAGES (KernelInitialSize));
160   }
161   if (CommandLine != NULL) {
162     FreePages (CommandLine, EFI_SIZE_TO_PAGES (CommandLineSize));
163   }
164   if (InitrdData != NULL) {
165     FreePages (InitrdData, EFI_SIZE_TO_PAGES (InitrdSize));
166   }
167 
168   return Status;
169 }
170 
171