├── Application ├── 2048 │ ├── 2048.inf │ ├── board.c │ ├── board.h │ └── main.c ├── AHCI │ ├── AHCI.c │ ├── AHCI.h │ └── AHCI.inf ├── GPT │ ├── GPT.c │ └── GPT.inf ├── HddId │ ├── HddId.c │ ├── HddId.h │ ├── HddId.inf │ ├── Misc.c │ └── Misc.h ├── HiiMenu │ ├── HiiForm1Strings.uni │ ├── HiiForm1Vfr.vfr │ ├── HiiMenu.c │ ├── HiiMenu.h │ ├── HiiMenu.inf │ └── HiiMenuGUIDs.h ├── bootmgr │ ├── bootmgr.c │ └── bootmgr.inf ├── ctest │ ├── ctest.c │ └── ctest.inf ├── mixbuild │ ├── MAKEFILE │ ├── iolib.asm │ ├── mixtest.c │ ├── mixtest.inf │ └── mk_mixtest.bat └── pwcycle │ ├── pwcycle.c │ ├── pwcycle.inf │ └── wiolib.asm ├── CSTAPP.sh ├── Include └── Library │ ├── AppCommon.h │ └── AppFrameWork.h ├── Library ├── AppCommonLib │ ├── AppCommonLib.c │ ├── AppCommonLib.h │ └── AppCommonLib.inf └── AppFrameWorkLib │ ├── AppFrameWorkLib.c │ ├── AppFrameWorkLib.h │ └── AppFrameWorkLib.inf ├── MyPkg.dec ├── MyPkg.dsc └── README.md /Application/2048/2048.inf: -------------------------------------------------------------------------------- 1 | ## 2 | # UEFI Application 3 | # 4 | # A shell application 5 | # 6 | # Free As Freedom @ 2015 7 | # 8 | # 9 | ## 10 | 11 | [Defines] 12 | INF_VERSION = 0x00010006 13 | BASE_NAME = 2048 14 | FILE_GUID = F995E121-C34B-4870-8083-8408E9A4C6E1 15 | MODULE_TYPE = UEFI_APPLICATION 16 | VERSION_STRING = 1.0 17 | ENTRY_POINT = ShellCEntryLib 18 | 19 | [Sources] 20 | main.c 21 | board.c 22 | board.h 23 | 24 | [Packages] 25 | MdePkg/MdePkg.dec 26 | MdeModulePkg/MdeModulePkg.dec 27 | ShellPkg/ShellPkg.dec 28 | MyPkg/MyPkg.dec 29 | 30 | [LibraryClasses] 31 | UefiApplicationEntryPoint 32 | UefiLib 33 | ShellCEntryLib 34 | LibC 35 | LibStdio 36 | 37 | [Protocols] 38 | 39 | -------------------------------------------------------------------------------- /Application/2048/board.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | GPLv3.0 FreeAsFreedom @2015 Kurt Qiao 4 | 5 | Abstract: 6 | 2048 char game in UEFI shell, 7 | shameless copy from https://github.com/clinew/2048 8 | 9 | --*/ 10 | #include "board.h" 11 | 12 | //pick different color for diff numbers, should use sqrt() 13 | int pick_color(int x){ 14 | 15 | //this array correspond to EFI console colours 16 | int mColor[11]={ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 }; 17 | int i; 18 | int rc=6; 19 | 20 | for (i=0; i<=10; i++){ 21 | if (mColor[i] == x) 22 | rc = i+1; 23 | } 24 | //if EFI_DARKGRAY, change to LIGHTCYAN 25 | if (rc == 9) 26 | rc = 0x0C; 27 | return rc; 28 | } 29 | 30 | int board_done(struct board* board) { 31 | int i; 32 | int j; 33 | int k; 34 | 35 | // Check for zeroes or winning number. 36 | for (i = 0; i < BOARD_ROWS; i++) { 37 | for (j = 0; j < BOARD_COLUMNS; j++) { 38 | if (!board->tiles[i][j]) { 39 | return 0; 40 | } else if (board->tiles[i][j] == WIN_NUMBER) { 41 | return 1; 42 | } 43 | } 44 | } 45 | 46 | // Check for possible horizontal merge. 47 | for (i = 0; i < BOARD_ROWS; i++) { 48 | j = -1; 49 | while ((k = ++j + 1) < BOARD_COLUMNS) { 50 | if (board->tiles[i][j] == board->tiles[i][k]) { 51 | return 0; 52 | } 53 | } 54 | } 55 | 56 | // Check for possible verical merge. 57 | for (i = 0; i < BOARD_COLUMNS; i++) { 58 | j = -1; 59 | while ((k = ++j + 1) < BOARD_ROWS) { 60 | if (board->tiles[j][i] == board->tiles[k][i]) { 61 | return 0; 62 | } 63 | } 64 | } 65 | 66 | // No possible merges. 67 | return -1; 68 | } 69 | 70 | unsigned board_get_tiles_empty(struct board* board) { 71 | int i; 72 | int j; 73 | unsigned count; 74 | 75 | // Calculate the number of empty tiles on the board. 76 | count = 0; 77 | for (i = 0; i < BOARD_ROWS; i++) { 78 | for (j = 0; j < BOARD_COLUMNS; j++) { 79 | count += (board->tiles[i][j] == 0); 80 | } 81 | } 82 | 83 | // Return the calculated number. 84 | return count; 85 | } 86 | 87 | void board_init(struct board* board) { 88 | int i; 89 | int j; 90 | 91 | // Initialize each tile. 92 | for (i = 0; i < BOARD_ROWS; i++) { 93 | for (j = 0; j < BOARD_COLUMNS; j++) { 94 | board->tiles[i][j] = 0; 95 | } 96 | } 97 | 98 | // Add two tiles to the board. 99 | board_plop(board); 100 | board_plop(board); 101 | } 102 | 103 | int board_merge_down(struct board* board) { 104 | int i; 105 | int j; 106 | int k; 107 | int merge; 108 | 109 | // Merge elements downwards. 110 | merge = 0; 111 | for (i = 0; i < BOARD_COLUMNS; i++) { 112 | j = BOARD_ROWS - 1; 113 | while (1) { 114 | // Find two potential elements to merge. 115 | while (j >= 0 && !board->tiles[j][i]) { 116 | j--; 117 | } 118 | k = j - 1; 119 | while (k >= 0 && !board->tiles[k][i]) { 120 | k--; 121 | } 122 | if (k < 0) { 123 | break; 124 | } 125 | 126 | // Try to merge the tiles. 127 | if (board->tiles[j][i] == board->tiles[k][i]) { 128 | board->tiles[k][i] += board->tiles[k][i]; 129 | board->tiles[j][i] = 0; 130 | j = k - 1; 131 | merge = 1; 132 | } else { 133 | j = k; 134 | } 135 | } 136 | 137 | } 138 | 139 | // Return whether an item was merged or not. 140 | return merge; 141 | } 142 | 143 | int board_merge_left(struct board* board) { 144 | int i; 145 | int j; 146 | int k; 147 | int merge; 148 | 149 | // Merge items leftwards. 150 | merge = 0; 151 | for (i = 0; i < BOARD_ROWS; i++) { 152 | j = 0; 153 | while (1) { 154 | // Two two potential tiles to merge. 155 | while (j < BOARD_COLUMNS && !board->tiles[i][j]) { 156 | j++; 157 | } 158 | k = j + 1; 159 | while (k < BOARD_COLUMNS && !board->tiles[i][k]) { 160 | k++; 161 | } 162 | if (k >= BOARD_COLUMNS) { 163 | break; 164 | } 165 | 166 | // Try to merge the tiles. 167 | if (board->tiles[i][j] == board->tiles[i][k]) { 168 | board->tiles[i][j] += board->tiles[i][j]; 169 | board->tiles[i][k] = 0; 170 | j = k + 1; 171 | merge = 1; 172 | } else { 173 | j = k; 174 | } 175 | } 176 | } 177 | 178 | // Return whether a tile was merged or not. 179 | return merge; 180 | } 181 | 182 | int board_merge_right(struct board* board) { 183 | int i; 184 | int j; 185 | int k; 186 | int merge; 187 | 188 | // Merge items rightward. 189 | merge = 0; 190 | for (i = 0; i < BOARD_ROWS; i++) { 191 | j = BOARD_ROWS - 1; 192 | while (1) { 193 | // Find potential tiles to merge. 194 | while (j >= 0 && !board->tiles[i][j]) { 195 | j--; 196 | } 197 | k = j - 1; 198 | while (k >= 0 && !board->tiles[i][k]) { 199 | k--; 200 | } 201 | if (k < 0) { 202 | break; 203 | } 204 | 205 | // Try to merge the tiles. 206 | if (board->tiles[i][j] == board->tiles[i][k]) { 207 | board->tiles[i][k] += board->tiles[i][k]; 208 | board->tiles[i][j] = 0; 209 | j = k - 1; 210 | merge = 1; 211 | } else { 212 | j = k; 213 | } 214 | } 215 | } 216 | 217 | // Return whether a tile was merged or not. 218 | return merge; 219 | } 220 | 221 | int board_merge_up(struct board* board) { 222 | int i; 223 | int j; 224 | int k; 225 | int merge; 226 | 227 | // Merge elements upwards. 228 | merge = 0; 229 | for (i = 0; i < BOARD_COLUMNS; i++) { 230 | j = 0; 231 | while (1) { 232 | // Find two potential tiles to merge. 233 | while (j < BOARD_ROWS && !board->tiles[j][i]) { 234 | j++; 235 | } 236 | k = j + 1; 237 | while (k < BOARD_ROWS && !board->tiles[k][i]) { 238 | k++; 239 | } 240 | if (k >= BOARD_ROWS) { 241 | break; 242 | } 243 | 244 | // Try to merge the tiles. 245 | if (board->tiles[j][i] == board->tiles[k][i]) { 246 | board->tiles[j][i] += board->tiles[j][i]; 247 | board->tiles[k][i] = 0; 248 | j = k + 1; 249 | merge = 1; 250 | } else { 251 | j = k; 252 | } 253 | } 254 | } 255 | 256 | // Return whether an item was merged or not. 257 | return merge; 258 | } 259 | 260 | int board_move_down(struct board* board) { 261 | char a = (char)board_merge_down(board); 262 | return a | board_shift_down(board); 263 | } 264 | 265 | int board_move_left(struct board* board) { 266 | char a = (char)board_merge_left(board); 267 | return a | board_shift_left(board); 268 | } 269 | 270 | int board_move_right(struct board* board) { 271 | char a = (char)board_merge_right(board); 272 | return a | board_shift_right(board); 273 | } 274 | 275 | int board_move_up(struct board* board) { 276 | char a = (char)board_merge_up(board); 277 | return a | board_shift_up(board); 278 | } 279 | 280 | void board_plop(struct board* board) { 281 | int i; 282 | int j; 283 | unsigned target; 284 | unsigned tiles_empty; 285 | 286 | // Count number of empty tiles. 287 | tiles_empty = board_get_tiles_empty(board); 288 | 289 | // Choose a random tile to palce the value into. 290 | target = rand() % tiles_empty; 291 | 292 | // Place the value into the tile. Implemented poorly. 293 | tiles_empty = 0; 294 | for (i = 0; i < BOARD_ROWS; i++) { 295 | for (j = 0; j < BOARD_COLUMNS; j++) { 296 | if (target == tiles_empty && board->tiles[i][j] == 0) { 297 | board->tiles[i][j] = (rand() % 100 <= 298 | BOARD_4SPAWN_CHANCE) ? 4 : 2; 299 | tiles_empty++; 300 | } else if (board->tiles[i][j] == 0) { 301 | tiles_empty++; 302 | } 303 | } 304 | } 305 | } 306 | 307 | void board_print(struct board* board) { 308 | int i; 309 | int j; 310 | 311 | // Print the board to 'stdout'. 312 | for (i = 0; i < BOARD_ROWS; i++) { 313 | Print(L" "); 314 | for (j = 0; j < BOARD_COLUMNS; j++) { 315 | if (board->tiles[i][j]) { 316 | gST->ConOut->SetAttribute(gST->ConOut, pick_color(board->tiles[i][j])|EFI_BACKGROUND_BLACK); 317 | Print(L"%4d ", board->tiles[i][j]); 318 | } else { 319 | gST->ConOut->SetAttribute(gST->ConOut,EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); 320 | Print(L" . "); 321 | } 322 | } 323 | Print(L"\n"); 324 | } 325 | } 326 | 327 | int board_shift_up(struct board* board) { 328 | int i; 329 | int j; 330 | unsigned k; 331 | int valid; 332 | 333 | // Shift tiles up the columns. 334 | valid = 0; 335 | for (i = 0; i < BOARD_COLUMNS; i++) { 336 | // Find first free tile in the column. 337 | k = 0; 338 | while (k < BOARD_ROWS && board->tiles[k][i]) { 339 | k++; 340 | } 341 | 342 | // Shift tiles up the column. 343 | for (j = k + 1; j < BOARD_ROWS; j++) { 344 | if (board->tiles[j][i]) { 345 | board->tiles[k++][i] = board->tiles[j][i]; 346 | board->tiles[j][i] = 0; 347 | valid = 1; 348 | } 349 | } 350 | } 351 | 352 | // Return move status. 353 | return valid; 354 | } 355 | 356 | int board_shift_down(struct board* board) { 357 | int i; 358 | int j; 359 | unsigned k; 360 | int valid; 361 | 362 | // Shift tiles down the columns. 363 | valid = 0; 364 | for (i = 0; i < BOARD_COLUMNS; i++) { 365 | // Find the last free tile in the column. 366 | k = BOARD_ROWS - 1; 367 | while (k >= 0 && board->tiles[k][i]) { 368 | k--; 369 | } 370 | 371 | // Shift tiles down the column. 372 | for (j = k - 1; j >= 0; j--) { 373 | if (board->tiles[j][i]) { 374 | board->tiles[k--][i] = board->tiles[j][i]; 375 | board->tiles[j][i] = 0; 376 | valid = 1; 377 | } 378 | } 379 | } 380 | 381 | // Return move status. 382 | return valid; 383 | } 384 | 385 | int board_shift_left(struct board* board) { 386 | int i; 387 | int j; 388 | unsigned k; 389 | int valid; 390 | 391 | // Shift tiles left across the rows. 392 | valid = 0; 393 | for (i = 0; i < BOARD_ROWS; i++) { 394 | // Find the first free tile in the row. 395 | k = 0; 396 | while (k < BOARD_COLUMNS && board->tiles[i][k]) { 397 | k++; 398 | } 399 | 400 | // Shift tiles left across the row. 401 | for (j = k + 1; j < BOARD_COLUMNS; j++) { 402 | if (board->tiles[i][j]) { 403 | board->tiles[i][k++] = board->tiles[i][j]; 404 | board->tiles[i][j] = 0; 405 | valid = 1; 406 | } 407 | } 408 | } 409 | 410 | // Return move status. 411 | return valid; 412 | } 413 | 414 | int board_shift_right(struct board* board) { 415 | int i; 416 | int j; 417 | unsigned k; 418 | int valid; 419 | 420 | // Shift tiles right across the rows. 421 | valid = 0; 422 | for (i = 0; i < BOARD_ROWS; i++) { 423 | // Find the last free tile in the row. 424 | k = BOARD_COLUMNS - 1; 425 | while (k >= 0 && board->tiles[i][k]) { 426 | k--; 427 | } 428 | 429 | // Shift tiles right across the row. 430 | for (j = k - 1; j >= 0; j--) { 431 | if (board->tiles[i][j]) { 432 | board->tiles[i][k--] = board->tiles[i][j]; 433 | board->tiles[i][j] = 0; 434 | valid = 1; 435 | } 436 | } 437 | } 438 | 439 | // Return move status. 440 | return valid; 441 | } 442 | -------------------------------------------------------------------------------- /Application/2048/board.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | GPLv3.0 FreeAsFreedom @2015 Kurt Qiao 4 | 5 | Abstract: 6 | 2048 char game in UEFI shell, 7 | shameless copy from https://github.com/clinew/2048 8 | 9 | --*/ 10 | #ifndef board_H 11 | #define board_H 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | #define BOARD_COLUMNS 4 24 | #define BOARD_ROWS 4 25 | 26 | // Likelihood of a '4' appearing on the board represented as a percentage 27 | // multiplied by 100. 28 | #define BOARD_4SPAWN_CHANCE 15 29 | 30 | #define WIN_NUMBER 2048 31 | /** 32 | * Represents the in-game board. 33 | */ 34 | struct board { 35 | // Holds the value of each tile. 36 | unsigned tiles[BOARD_ROWS][BOARD_COLUMNS]; 37 | }; 38 | 39 | 40 | /** 41 | * Returns 0 if the game is not over; >0 if the game is over and the user 42 | * has won, or <0 if the user has lost. 43 | */ 44 | int board_done(struct board* board); 45 | 46 | /** 47 | * Returns the number of empty tiles in the board. 48 | */ 49 | unsigned board_get_tiles_empty(struct board* board); 50 | 51 | /** 52 | * Initializes the specified board. 53 | */ 54 | void board_init(struct board* board); 55 | 56 | /** 57 | * Merge tiles in the board downwards. 58 | */ 59 | int board_merge_down(struct board* board); 60 | 61 | /** 62 | * Merge tiles in the board leftwards. 63 | */ 64 | int board_merge_left(struct board* board); 65 | 66 | /** 67 | * Merge tiles in the board rightwards. 68 | */ 69 | int board_merge_right(struct board* board); 70 | 71 | /** 72 | * Merge tiles in the board upwards. 73 | */ 74 | int board_merge_up(struct board* board); 75 | 76 | /** 77 | * Processes user move-down request. 78 | */ 79 | int board_move_down(struct board* board); 80 | 81 | /** 82 | * Process user move-left request. 83 | */ 84 | int board_move_left(struct board* board); 85 | 86 | /** 87 | * Process user move-right request. 88 | */ 89 | int board_move_right(struct board* board); 90 | 91 | /** 92 | * Process user move-up request. 93 | */ 94 | int board_move_up(struct board* board); 95 | 96 | /** 97 | * Spawn a new tile on the board. 98 | * 99 | * I didn't know what to call this, so "plopping" a value on the board sounds 100 | * legit enough. 101 | */ 102 | void board_plop(struct board* board); 103 | 104 | /** 105 | * Print the board to 'stdout'. 106 | */ 107 | void board_print(struct board* board); 108 | 109 | /** 110 | * Shift all the elements in the board down. 111 | */ 112 | int board_shift_down(struct board* board); 113 | 114 | /** 115 | * Shift all the elements in the board left. 116 | */ 117 | int board_shift_left(struct board* board); 118 | 119 | /** 120 | * Shift all the elements in the board right. 121 | */ 122 | int board_shift_right(struct board* board); 123 | 124 | /** 125 | * Shift all the elements in the board up. 126 | */ 127 | int board_shift_up(struct board* board); 128 | 129 | 130 | #endif // board_H 131 | -------------------------------------------------------------------------------- /Application/2048/main.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | GPLv3.0 FreeAsFreedom @2015 Kurt Qiao 4 | 5 | Abstract: 6 | 2048 char game in UEFI shell, 7 | shameless copy from https://github.com/clinew/2048 8 | 9 | Revision History 10 | v0.1 2015/4/8 kurt 1. optimzied fix show and color number 11 | 2. implement leave game key 12 | 3. show movement counter 13 | --*/ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "board.h" 20 | 21 | int main( 22 | int argc, 23 | char* argv[] 24 | ) 25 | { 26 | struct board board; 27 | int status; // Game status. 28 | int valid; 29 | EFI_STATUS EStatus; 30 | EFI_INPUT_KEY key; 31 | UINTN Index; 32 | UINTN move; 33 | 34 | EStatus = EFI_SUCCESS; 35 | move = 0; 36 | 37 | // Set up board. 38 | board_init(&board); 39 | 40 | // Play the game. 41 | status = board_done(&board); 42 | while (!(status)) { 43 | 44 | 45 | gST->ConOut->SetCursorPosition(gST->ConOut, 0, 17); 46 | // Print the board. 47 | board_print(&board); 48 | 49 | // Get the player's move. 50 | valid = 0; 51 | 52 | //wait for key press 53 | EStatus = gBS->WaitForEvent(1, &(gST->ConIn->WaitForKey), &Index); 54 | EStatus = gST->ConIn->ReadKeyStroke(gST->ConIn, &key); 55 | //clear status message 56 | EStatus = gST->ConOut->SetCursorPosition(gST->ConOut, 25, 17); 57 | Print(L" "); 58 | 59 | 60 | if (key.UnicodeChar == L'w'|| key.ScanCode == 0x01){ 61 | valid = board_move_up(&board); 62 | } else if (key.UnicodeChar == L's'|| key.ScanCode == 0x02){ 63 | valid = board_move_down(&board); 64 | } else if (key.UnicodeChar == L'a'|| key.ScanCode == 0x04){ 65 | valid = board_move_left(&board); 66 | } else if (key.UnicodeChar == L'd'|| key.ScanCode == 0x03){ 67 | valid = board_move_right(&board); 68 | } else if (key.UnicodeChar == L'l'){ 69 | EStatus = gST->ConOut->SetCursorPosition(gST->ConOut, 25, 17); 70 | Print(L"Leave game!"); 71 | gST->ConOut->SetAttribute(gST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); 72 | return EFI_SUCCESS; 73 | } else { 74 | //do nothing when press other keys 75 | continue; 76 | } 77 | 78 | // Prepare for user's next move. 79 | if (valid) { 80 | board_plop(&board); 81 | } else { 82 | gST->ConOut->SetCursorPosition(gST->ConOut, 25, 17); 83 | Print(L"Invalid move."); 84 | } 85 | status = board_done(&board); 86 | 87 | //show movement counter 88 | EStatus = gST->ConOut->SetCursorPosition(gST->ConOut, 30, 20); 89 | Print(L" [%d] ", ++move); 90 | } 91 | 92 | // Print the final board. 93 | gST->ConOut->SetCursorPosition(gST->ConOut, 25, 17); 94 | gST->ConOut->SetAttribute(gST->ConOut, EFI_RED|EFI_BACKGROUND_BLACK); 95 | Print(L"Game over, you %s!", (status < 0) ? L"LOSE" : L"WIN"); 96 | 97 | gST->ConOut->SetCursorPosition(gST->ConOut, 0, 17); 98 | board_print(&board); 99 | 100 | gST->ConOut->SetAttribute(gST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); 101 | // Return success. 102 | return EStatus; 103 | } 104 | -------------------------------------------------------------------------------- /Application/AHCI/AHCI.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2014 Kurt Qiao 4 | 5 | Module Name: 6 | 7 | AHCI.c 8 | 9 | Abstract: 10 | a program help to understan AHCI operation. 11 | simply get AHCI device identify data 12 | 13 | Revision History 14 | 15 | --*/ 16 | 17 | 18 | #include "AHCI.h" 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "Library/UefiBootServicesTableLib.h" 26 | 27 | HBA_MEM *abar; 28 | BOOLEAN EjectODD = FALSE; 29 | /*VOID 30 | ResetAhciEngine( 31 | HBA_MEM *abar 32 | );*/ 33 | 34 | EFI_STATUS 35 | AhciIssueCmd( 36 | HBA_PORT *port, 37 | UINT32 cmdslot); 38 | 39 | VOID 40 | BuildH2DFis( 41 | FIS_REG_H2D *fish2d, 42 | UINT8 cmd 43 | ); 44 | 45 | EFI_STATUS 46 | ATAPIEjectODD( 47 | HBA_MEM *abar, 48 | FIS_REG_H2D *fish2d, 49 | HBA_CMD_HEADER *cmdlist, 50 | HBA_CMD_TBL *cmdheader 51 | ); 52 | 53 | EFI_STATUS 54 | EFIAPI 55 | ShellAppMain ( 56 | IN UINTN Argc, 57 | IN CHAR16 **Argv 58 | ) 59 | { 60 | 61 | EFI_STATUS Status=EFI_SUCCESS; 62 | UINT32 ip; 63 | UINTN i, PortAddr; 64 | DATA_64 Data64; 65 | UINT64 *AhciPciAddr=NULL; 66 | 67 | HBA_PORT *port; 68 | UINT8 *tmpbuffer, classinter, cmd; 69 | HBA_CMD_HEADER *cmdlist; 70 | HBA_CMD_TBL *cmdheader; 71 | FIS_REG_H2D *fish2d; 72 | 73 | //use AHCI.efi -e to eject ODD 74 | if (Argv[1][1] == L'e'){ 75 | EjectODD = TRUE; 76 | } 77 | ZeroMem(AhciPciAddr, sizeof(UINT64)); 78 | //get AHCI controller 79 | classinter = 0x01; 80 | if (!AppProbePCIByClassCode(0x01, 0x06,&classinter, AhciPciAddr)) 81 | return EFI_NOT_FOUND; 82 | 83 | //read AHCI bar 84 | abar = (HBA_MEM *)(UINTN)(PciRead32((UINTN)(*AhciPciAddr+0x24))); 85 | 86 | //make sure AHCI enable 87 | if (!(abar->ghc & BIT31)) 88 | abar->ghc |= BIT31; 89 | 90 | //allocate buffer for read return data 91 | tmpbuffer = AllocateZeroPool(sizeof(UINT8)*512); 92 | 93 | //allocate alignment memory for command table 94 | cmdheader = AllocatePages(sizeof(HBA_CMD_TBL)); 95 | ZeroMem(cmdheader, sizeof(HBA_CMD_TBL)); 96 | 97 | //allocate h2d FIS 98 | fish2d = AllocateZeroPool(sizeof(FIS_REG_H2D)); 99 | 100 | //allocate align memory address for command list, PxCLB bit9:0 is reserved 101 | cmdlist = AllocatePages(sizeof(HBA_CMD_HEADER)); 102 | ZeroMem(cmdlist, sizeof(HBA_CMD_HEADER)); 103 | 104 | if (EjectODD){ 105 | Status = ATAPIEjectODD(abar, fish2d, cmdlist, cmdheader); 106 | Print(L"SATA AHCI Mode ODD eject!\n"); 107 | return Status; 108 | } 109 | 110 | Print(L"AHCI controller address: %x\n", *AhciPciAddr); 111 | Print(L"AHCI bar: %x\n", abar); 112 | Print(L"Host Capabilities: %x ; Global Host Control: %x\n", abar->cap, abar->ghc); 113 | Print(L"Port Implemented: %x \n", abar->pi); 114 | //scan port for ATA/ATAPI device and print identify data 115 | cmd = ATA_CMD_IDENTIFY; 116 | //check implemented port 117 | for (ip = abar->pi, i=0; ip>0;ip>>=1, i++){ 118 | 119 | if (ip&1){ 120 | 121 | PortAddr = (UINTN)abar + 0x100 + 0x80*i; 122 | Print(L"\nport: %d, address: %x\n", i, PortAddr); 123 | port = (HBA_PORT *)(UINTN) PortAddr; 124 | if (port->sig == ATADRIVE) 125 | cmd = ATA_CMD_IDENTIFY; 126 | if (port->sig == ATAPIDRIVE) 127 | cmd = ATAPI_CMD_IDENTIFY; 128 | 129 | BuildH2DFis(fish2d, cmd); 130 | CopyMem(cmdheader->cfis, fish2d, sizeof(FIS_REG_H2D)); 131 | cmdheader->prdt_entry[0].dba = (UINT32)(UINTN) tmpbuffer; 132 | cmdheader->prdt_entry[0].dbc = 0x1ff; 133 | cmdheader->prdt_entry[0].i = 1; 134 | 135 | cmdlist->cfl = 5; 136 | cmdlist->prdtl = 1; 137 | cmdlist->ctba = (UINT32)(UINTN) cmdheader; 138 | 139 | Data64.Uint64 = (UINTN)cmdlist; 140 | port->clb = Data64.Uint32.Lower32; 141 | port->clbu = Data64.Uint32.Upper32; 142 | 143 | Status = AhciIssueCmd(port, BIT0); 144 | if (EFI_ERROR(Status)){ 145 | Print(L"Issue cmd fail! Need to Kick AHCI engine\n"); 146 | continue; 147 | } 148 | AppPrintBuffer((UINT16 *)tmpbuffer); 149 | Print(L"\n"); 150 | } 151 | } 152 | 153 | return Status; 154 | } 155 | 156 | /*VOID 157 | ResetAhciEngine( 158 | HBA_MEM *abar 159 | ) 160 | { 161 | UINTN i; 162 | Print(L"\n!!kick the engine!!\n"); 163 | abar->ghc |= BIT0; 164 | //wait cmd 165 | for(i=0; i<100; i++){ 166 | gBS->Stall(500); 167 | if (!(abar->ghc & BIT0)) 168 | break; 169 | } 170 | abar->ghc |= BIT31; 171 | gBS->Stall(500); 172 | }*/ 173 | 174 | EFI_STATUS 175 | AhciIssueCmd( 176 | HBA_PORT *port, 177 | UINT32 cmdslot 178 | ) 179 | { 180 | UINTN i; 181 | EFI_STATUS Status = EFI_SUCCESS; 182 | 183 | //make sure bit0 Start set to enable process cmd list 184 | if(!(port->cmd & 1)) 185 | port->cmd |= BIT0|BIT4; 186 | //clear status 187 | port->serr = port->serr; 188 | port->is = port->is; 189 | 190 | //if err status or busy, reset PxCMD. 191 | if ((port->is &(BIT30|BIT29|BIT28|BIT27|BIT26|BIT24|BIT23)) || \ 192 | (port->tfd &(BIT0|BIT7))){ 193 | port->cmd &= ~BIT0; 194 | //Start|Command List Override|FIS Receive Enable 195 | port->cmd |= BIT0|BIT3|BIT4; 196 | port->is = port->is; 197 | } 198 | 199 | //if (port->tfd & BIT0) 200 | // return EFI_DEVICE_ERROR; 201 | //issue cmd 202 | port->ci = cmdslot; 203 | 204 | //wait cmd 205 | for(i=0; i<100; i++){ 206 | gBS->Stall(500); 207 | if (!(port->tfd & BIT7)) 208 | break; 209 | } 210 | 211 | if (port->tfd & BIT0) 212 | Status = EFI_DEVICE_ERROR; 213 | 214 | return Status; 215 | } 216 | 217 | VOID 218 | BuildH2DFis( 219 | FIS_REG_H2D *fish2d, 220 | UINT8 cmd 221 | ) 222 | { 223 | //initial H2D FIS (Serial ATA Revision 2.6 specification) 224 | // +-+-------------+--------------+----------------+---------------+ 225 | // |0| Features | Command |0|C|R|R|R|PmPort| FIS Type (27h)| 226 | // +-+-------------+--------------+----------------+---------------+ 227 | // |1| Device | LBA High | LBA Mid | LBA Low | 228 | // +-+-------------+--------------+----------------+---------------+ 229 | // |2|Features(exp)|LBA High (exp)| LBA Mid (exp) | LBA Low (exp) | 230 | // +-+-------------+--------------+----------------+---------------+ 231 | // |3| Control | Reserved (0) |SectorCount(exp)| Sector Count | 232 | // +-+-------------+--------------+----------------+---------------+ 233 | // |4| Reserved (0)| Reserved (0) | Reserved (0) | Reserved (0) | 234 | // +-+-------------+--------------+----------------+---------------+ 235 | fish2d->fis_type = FIS_TYPE_REG_H2D; 236 | fish2d->pmport = 0; 237 | fish2d->c = 1; 238 | fish2d->command = cmd; 239 | fish2d->featurel = 1; 240 | 241 | } 242 | 243 | EFI_STATUS 244 | ATAPIEjectODD( 245 | HBA_MEM *abar, 246 | FIS_REG_H2D *fish2d, 247 | HBA_CMD_HEADER *cmdlist, 248 | HBA_CMD_TBL *cmdheader 249 | ) 250 | { 251 | EFI_STATUS Status = EFI_NOT_FOUND; 252 | UINT32 ip; //implemented port 253 | UINTN i, PortAddr; 254 | HBA_PORT *port; 255 | DATA_64 Data64; 256 | 257 | //scan implemented port 258 | for (ip = abar->pi, i=0; ip>0;ip>>=1, i++){ 259 | if (ip&1){ 260 | PortAddr = (UINTN)abar + 0x100 + 0x80*i; 261 | port = (HBA_PORT *)(UINTN) PortAddr; 262 | //found ODD and issue eject command 263 | if (port->sig == ATAPIDRIVE){ 264 | //setting ATAPI cmd enable FIS 265 | BuildH2DFis(fish2d, 0xA0); 266 | //setting command header 267 | CopyMem(cmdheader->cfis, fish2d, sizeof(FIS_REG_H2D)); 268 | 269 | cmdheader->prdt_entry[0].i = 1; 270 | 271 | cmdheader->acmd[0] = 0x1B; //START STOP UNIT Command 272 | cmdheader->acmd[4] = 0x02; //LOEJ bit 273 | 274 | cmdlist->cfl = 5; 275 | cmdlist->prdtl = 1; 276 | cmdlist->a = 1; //enable ATAPI cmd 277 | cmdlist->ctba = (UINT32)(UINTN) cmdheader; 278 | 279 | Data64.Uint64 = (UINTN)cmdlist; 280 | port->clb = Data64.Uint32.Lower32; 281 | port->clbu = Data64.Uint32.Upper32; 282 | 283 | Status = AhciIssueCmd(port, BIT0); 284 | break; 285 | } 286 | } 287 | } 288 | 289 | return Status; 290 | } 291 | -------------------------------------------------------------------------------- /Application/AHCI/AHCI.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _APP_AHCI_H_ 3 | #define _APP_AHCI_H_ 4 | 5 | //define signature 6 | #define ATADRIVE 0x00000101 7 | #define ATAPIDRIVE 0xEB140101 8 | 9 | typedef struct { 10 | UINT32 Lower32; 11 | UINT32 Upper32; 12 | } DATA_32; 13 | 14 | typedef union { 15 | DATA_32 Uint32; 16 | UINT64 Uint64; 17 | } DATA_64; 18 | 19 | //too lazy to construct my own structure, 20 | //just copy form here: http://wiki.osdev.org/AHCI 21 | 22 | //Port Ctrl Register 23 | typedef volatile struct tagHBA_PORT 24 | { 25 | UINT32 clb; // 0x00, command list base address, 1K-UINT8 aligned 26 | UINT32 clbu; // 0x04, command list base address upper 32 bits 27 | UINT32 fb; // 0x08, FIS base address, 256-UINT8 aligned 28 | UINT32 fbu; // 0x0C, FIS base address upper 32 bits 29 | UINT32 is; // 0x10, interrupt status 30 | UINT32 ie; // 0x14, interrupt enable 31 | UINT32 cmd; // 0x18, command and status 32 | UINT32 rsv0; // 0x1C, Reserved 33 | UINT32 tfd; // 0x20, task file data 34 | UINT32 sig; // 0x24, signature 35 | UINT32 ssts; // 0x28, SATA status (SCR0:SStatus) 36 | UINT32 sctl; // 0x2C, SATA control (SCR2:SControl) 37 | UINT32 serr; // 0x30, SATA error (SCR1:SError) 38 | UINT32 sact; // 0x34, SATA active (SCR3:SActive) 39 | UINT32 ci; // 0x38, command issue 40 | UINT32 sntf; // 0x3C, SATA notification (SCR4:SNotification) 41 | UINT32 fbs; // 0x40, FIS-based switch control 42 | UINT32 rsv1[11]; // 0x44 ~ 0x6F, Reserved 43 | UINT32 vendor[4]; // 0x70 ~ 0x7F, vendor specific 44 | } HBA_PORT; 45 | 46 | //HBA Memory Registers 47 | typedef volatile struct tagHBA_MEM 48 | { 49 | // 0x00 - 0x2B, Generic Host Control 50 | UINT32 cap; // 0x00, Host capability 51 | UINT32 ghc; // 0x04, Global host control 52 | UINT32 is; // 0x08, Interrupt status 53 | UINT32 pi; // 0x0C, Port implemented 54 | UINT32 vs; // 0x10, Version 55 | UINT32 ccc_ctl; // 0x14, Command completion coalescing control 56 | UINT32 ccc_pts; // 0x18, Command completion coalescing ports 57 | UINT32 em_loc; // 0x1C, Enclosure management location 58 | UINT32 em_ctl; // 0x20, Enclosure management control 59 | UINT32 cap2; // 0x24, Host capabilities extended 60 | UINT32 bohc; // 0x28, BIOS/OS handoff control and status 61 | 62 | // 0x2C - 0x9F, Reserved 63 | UINT8 rsv[0xA0-0x2C]; 64 | 65 | // 0xA0 - 0xFF, Vendor specific registers 66 | UINT8 vendor[0x100-0xA0]; 67 | 68 | // 0x100 - 0x10FF, Port control registers 69 | HBA_PORT ports[1]; // 1 ~ 32 70 | } HBA_MEM; 71 | 72 | //Port Command List 73 | typedef struct tagHBA_CMD_HEADER 74 | { 75 | // DW0 76 | UINT8 cfl:5; // Command FIS length in UINT32S, 2 ~ 16 77 | UINT8 a:1; // ATAPI 78 | UINT8 w:1; // Write, 1: H2D, 0: D2H 79 | UINT8 p:1; // Prefetchable 80 | 81 | UINT8 r:1; // Reset 82 | UINT8 b:1; // BIST 83 | UINT8 c:1; // Clear busy upon R_OK 84 | UINT8 rsv0:1; // Reserved 85 | UINT8 pmp:4; // Port multiplier port 86 | 87 | UINT16 prdtl; // Physical region descriptor table length in entries 88 | 89 | // DW1 90 | volatile 91 | UINT32 prdbc; // Physical region descriptor UINT8 count transferred 92 | 93 | // DW2, 3 94 | UINT32 ctba; // Command table descriptor base address 95 | UINT32 ctbau; // Command table descriptor base address upper 32 bits 96 | 97 | // DW4 - 7 98 | UINT32 rsv1[4]; // Reserved 99 | } HBA_CMD_HEADER; 100 | 101 | //Command Table 102 | typedef struct tagHBA_PRDT_ENTRY 103 | { 104 | UINT32 dba; // Data base address 105 | UINT32 dbau; // Data base address upper 32 bits 106 | UINT32 rsv0; // Reserved 107 | 108 | // DW3 109 | UINT32 dbc:22; // UINT8 count, 4M max 110 | UINT32 rsv1:9; // Reserved 111 | UINT32 i:1; // Interrupt on completion 112 | } HBA_PRDT_ENTRY; 113 | 114 | typedef struct tagHBA_CMD_TBL 115 | { 116 | // 0x00 117 | UINT8 cfis[64]; // Command FIS 118 | 119 | // 0x40 120 | UINT8 acmd[16]; // ATAPI command, 12 or 16 UINT8s 121 | 122 | // 0x50 123 | UINT8 rsv[48]; // Reserved 124 | 125 | // 0x80 126 | HBA_PRDT_ENTRY prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535 127 | } HBA_CMD_TBL; 128 | 129 | 130 | 131 | typedef enum 132 | { 133 | FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device 134 | FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host 135 | FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host 136 | FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional 137 | FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional 138 | FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional 139 | FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host 140 | FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host 141 | } FIS_TYPE; 142 | 143 | typedef struct tagFIS_REG_H2D 144 | { 145 | // UINT32 0 146 | UINT8 fis_type; // FIS_TYPE_REG_H2D 147 | 148 | UINT8 pmport:4; // Port multiplier 149 | UINT8 rsv0:3; // Reserved 150 | UINT8 c:1; // 1: Command, 0: Control 151 | 152 | UINT8 command; // Command register 153 | UINT8 featurel; // Feature register, 7:0 154 | 155 | // UINT32 1 156 | UINT8 lba0; // LBA low register, 7:0 157 | UINT8 lba1; // LBA mid register, 15:8 158 | UINT8 lba2; // LBA high register, 23:16 159 | UINT8 device; // Device register 160 | 161 | // UINT32 2 162 | UINT8 lba3; // LBA register, 31:24 163 | UINT8 lba4; // LBA register, 39:32 164 | UINT8 lba5; // LBA register, 47:40 165 | UINT8 featureh; // Feature register, 15:8 166 | 167 | // UINT32 3 168 | UINT8 countl; // Count register, 7:0 169 | UINT8 counth; // Count register, 15:8 170 | UINT8 icc; // Isochronous command completion 171 | UINT8 control; // Control register 172 | 173 | // UINT32 4 174 | UINT8 rsv1[4]; // Reserved 175 | } FIS_REG_H2D; 176 | 177 | 178 | 179 | 180 | 181 | #endif //_APP_AHCI_H_ 182 | -------------------------------------------------------------------------------- /Application/AHCI/AHCI.inf: -------------------------------------------------------------------------------- 1 | ## 2 | # Sample UEFI Application Reference EDKII Module 3 | # 4 | # A sample shell application 5 | # 6 | # Copyright (c) 2012 - 2014, KurtQiao. All rights reserved.
7 | # 8 | # 9 | ## 10 | 11 | [Defines] 12 | INF_VERSION = 0x00010006 13 | BASE_NAME = AHCI 14 | FILE_GUID = 032B3E70-52C0-46e6-86CD-DCC32B906DFF 15 | MODULE_TYPE = UEFI_APPLICATION 16 | VERSION_STRING = 1.0 17 | ENTRY_POINT = ShellCEntryLib 18 | 19 | # 20 | # The following information is for reference only and not required by the build tools. 21 | # 22 | # VALID_ARCHITECTURES = IA32 X64 IPF EBC 23 | # 24 | 25 | [Sources] 26 | AHCI.c 27 | AHCI.h 28 | 29 | [Packages] 30 | MdePkg/MdePkg.dec 31 | MdeModulePkg/MdeModulePkg.dec 32 | ShellPkg/ShellPkg.dec 33 | MyPkg/MyPkg.dec 34 | 35 | [LibraryClasses] 36 | UefiApplicationEntryPoint 37 | UefiLib 38 | ShellCEntryLib 39 | PciLib 40 | AppCommonLib 41 | 42 | [Protocols] 43 | gEfiPciRootBridgeIoProtocolGuid 44 | gEfiPciIoProtocolGuid -------------------------------------------------------------------------------- /Application/GPT/GPT.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "Library/UefiBootServicesTableLib.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | 13 | EFI_STATUS 14 | DumpDevicePath(); 15 | 16 | EFI_STATUS 17 | EFIAPI 18 | ShellAppMain ( 19 | IN UINTN Argc, 20 | IN CHAR16 **Argv 21 | ) 22 | { 23 | 24 | EFI_STATUS Status; 25 | EFI_BLOCK_IO_PROTOCOL *BlkIo; 26 | EFI_HANDLE *BlkIoHandle; 27 | UINT32 BlockSize; 28 | UINTN Index; 29 | UINTN NoBlkIoHandles; 30 | EFI_DEVICE_PATH_PROTOCOL *DevPath; 31 | CHAR16 *DevPathString; 32 | EFI_PARTITION_TABLE_HEADER *PartHdr; 33 | MASTER_BOOT_RECORD *PMBR; 34 | 35 | // 36 | // Locate Handles that support BlockIo protocol 37 | // 38 | Status = gBS->LocateHandleBuffer ( 39 | ByProtocol, 40 | &gEfiBlockIoProtocolGuid, 41 | NULL, 42 | &NoBlkIoHandles, 43 | &BlkIoHandle 44 | ); 45 | if (EFI_ERROR (Status)) { 46 | return Status; 47 | } 48 | 49 | for (Index = 0; Index < NoBlkIoHandles; Index++) { 50 | Status = gBS->HandleProtocol ( 51 | BlkIoHandle[Index], 52 | &gEfiBlockIoProtocolGuid, 53 | (VOID **) &BlkIo 54 | ); 55 | if (EFI_ERROR (Status)) { 56 | continue; 57 | } 58 | if(BlkIo->Media->LogicalPartition){ //if partition skip 59 | continue; 60 | } 61 | DevPath = DevicePathFromHandle(BlkIoHandle[Index]); 62 | if (DevPath == NULL){ 63 | continue; 64 | } 65 | DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE); 66 | Print(L"%s \nMedia Id: %d, device type: %x, SubType: %x, logical: %x\n", \ 67 | DevPathString, BlkIo->Media->MediaId, DevPath->Type, DevPath->SubType, \ 68 | BlkIo->Media->LogicalPartition); 69 | 70 | BlockSize = BlkIo->Media->BlockSize; 71 | PartHdr = AllocateZeroPool (BlockSize); 72 | PMBR = AllocateZeroPool (BlockSize); 73 | //read LBA0 74 | Status = BlkIo->ReadBlocks( 75 | BlkIo, 76 | BlkIo->Media->MediaId, 77 | (EFI_LBA)0, //LBA 0, MBR/Protetive MBR 78 | BlockSize, 79 | PMBR 80 | ); 81 | //read LBA1 82 | Status = BlkIo->ReadBlocks( 83 | BlkIo, 84 | BlkIo->Media->MediaId, 85 | (EFI_LBA)1, //LBA 1, GPT 86 | BlockSize, 87 | PartHdr 88 | ); 89 | //check if GPT 90 | if (PartHdr->Header.Signature == EFI_PTAB_HEADER_ID){ 91 | 92 | if (PMBR->Signature == MBR_SIGNATURE){ 93 | Print(L"Found Protetive MBR.\n"); 94 | } 95 | Print(L"LBA 1,"); 96 | Print(L"GPT:\n"); 97 | // 98 | //you can add some parse GPT data structure here 99 | // 100 | AppPrintBuffer((UINT16 *)PartHdr); 101 | Print(L"\n"); 102 | }else{ 103 | if (PMBR->Signature == MBR_SIGNATURE){ 104 | Print(L"LBA 0,"); 105 | Print(L"MBR:\n"); 106 | AppPrintBuffer((UINT16 *)PMBR); 107 | Print(L"\n"); 108 | } 109 | } 110 | 111 | FreePool(PartHdr); 112 | FreePool(PMBR); 113 | } 114 | 115 | //debug dump device path 116 | //DumpDevicePath(); 117 | return Status; 118 | } 119 | 120 | EFI_STATUS 121 | DumpDevicePath() 122 | { 123 | EFI_STATUS Status; 124 | UINTN HandlesCount; 125 | UINTN Index; 126 | EFI_HANDLE *DevPathHandle; 127 | EFI_DEVICE_PATH_PROTOCOL *DevPath; 128 | 129 | // 130 | // Locate Handles that support BlockIo protocol 131 | // 132 | Status = gBS->LocateHandleBuffer ( 133 | ByProtocol, 134 | &gEfiDevicePathProtocolGuid, 135 | NULL, 136 | &HandlesCount, 137 | &DevPathHandle 138 | ); 139 | if (!EFI_ERROR (Status)) { 140 | Print(L"Device Path Protocol Handles: %d\n", HandlesCount); 141 | Print(L"Type SubType Length Str\n"); 142 | for (Index = 0; Index < HandlesCount; Index++) { 143 | Status = gBS->HandleProtocol ( 144 | DevPathHandle[Index], 145 | &gEfiDevicePathProtocolGuid, 146 | (VOID **) &DevPath 147 | ); 148 | Print(L"%x %x %x %s\n",DevPath->Type, DevPath->SubType, DevPath->Length, ConvertDevicePathToText(DevPath, TRUE, FALSE)); 149 | } 150 | } 151 | return EFI_SUCCESS; 152 | } 153 | -------------------------------------------------------------------------------- /Application/GPT/GPT.inf: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Defines] 4 | INF_VERSION = 0x00010006 5 | BASE_NAME = GPT 6 | FILE_GUID = 614838D3-DFF2-4773-A412-4DBA3B3A11D4 7 | MODULE_TYPE = UEFI_APPLICATION 8 | VERSION_STRING = 1.0 9 | ENTRY_POINT = ShellCEntryLib 10 | 11 | # 12 | # The following information is for reference only and not required by the build tools. 13 | # 14 | # VALID_ARCHITECTURES = IA32 X64 IPF EBC 15 | # 16 | 17 | [Sources] 18 | GPT.c 19 | 20 | [Packages] 21 | MdePkg/MdePkg.dec 22 | MdeModulePkg/MdeModulePkg.dec 23 | ShellPkg/ShellPkg.dec 24 | MyPkg/MyPkg.dec 25 | 26 | [LibraryClasses] 27 | UefiApplicationEntryPoint 28 | UefiLib 29 | ShellCEntryLib 30 | PciLib 31 | AppFrameWorkLib 32 | AppCommonLib 33 | 34 | [Protocols] 35 | gEfiBlockIoProtocolGuid -------------------------------------------------------------------------------- /Application/HddId/HddId.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2014 Kurt Qiao 4 | 5 | Module Name: 6 | 7 | HddId.c 8 | 9 | Abstract: 10 | HddId app 11 | 12 | Revision History 13 | 14 | --*/ 15 | 16 | 17 | #include "HddId.h" 18 | #include "Misc.h" 19 | #include 20 | #include 21 | 22 | EFI_STATUS 23 | InitializeFrameworkTable( 24 | IN UINTN Argc, 25 | IN CHAR16 **Argv 26 | ); 27 | 28 | EFI_APP_FRAMEWORK_TABLE gFT = { 29 | InitializeFrameworkTable, //Init 30 | Print_Help, //AppPrintHelp 31 | {0}, //Operations 32 | NULL, //PROTOCOL1 (save EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL) 33 | NULL, //PROTOCOL2 (save EFI_ATA_PASS_THRU_PROTOCOL) 34 | NULL //OP1 (not use) 35 | }; 36 | 37 | 38 | EFI_STATUS 39 | EFIAPI 40 | ShellAppMain ( 41 | IN UINTN Argc, 42 | IN CHAR16 **Argv 43 | ) 44 | { 45 | EFI_STATUS Status=EFI_SUCCESS; 46 | EFI_ATA_DEVICES *ATADevice=NULL; 47 | UINT8 tmpbuffer[512]; 48 | UINT8 *bufferptr; 49 | 50 | // 51 | gFT.Init(Argc, Argv); 52 | // 53 | DetectATAController(ATADevice); 54 | 55 | ZeroMem(tmpbuffer, sizeof(UINT8)*512); 56 | bufferptr = tmpbuffer; 57 | 58 | if(gFT.Operations.APP_OPERATIONS_PRINT_TEXT){ 59 | if (ATADevice->ATATypte == SATA_AHCI_1){ 60 | //typically only one AHCI controller, so we not support more than one AHCI here 61 | AHCI_HDD_Identify(ATADevice->ATA_CONTROLLER_ADDRESS[0], bufferptr); 62 | } 63 | if (ATADevice->ATATypte == IDE_CONTROLLER){ 64 | IDE_HDD_Identify(ATADevice, (UINT16 *)bufferptr); 65 | } 66 | 67 | } 68 | if(gFT.Operations.APP_OPERATIONS_PRINT_HELP){ 69 | gFT.AppPrintHelp(); 70 | } 71 | 72 | return Status; 73 | } 74 | 75 | EFI_STATUS 76 | InitializeFrameworkTable( 77 | IN UINTN Argc, 78 | IN CHAR16 **Argv 79 | ) 80 | { 81 | EFI_STATUS Status; 82 | 83 | Status = ParseCommandLine(Argc, Argv, &gFT); 84 | if (EFI_ERROR(Status)) 85 | { 86 | Print(L"Wrong parameters usage!\n"); 87 | return Status; 88 | } 89 | //save protocol for future use, so we only locate it when program init 90 | Status = gBS->LocateProtocol(&gEfiPciRootBridgeIoProtocolGuid, 91 | NULL, 92 | (VOID**)&gFT.PROTOCOL1 93 | ); 94 | if(EFI_ERROR(Status)){ 95 | Print(L"Locate PciRootBridgeIoProtocol Fail!\n"); 96 | return Status; 97 | } 98 | 99 | Status = gBS->LocateProtocol(&gEfiAtaPassThruProtocolGuid, 100 | NULL, 101 | (VOID **) &gFT.PROTOCOL2 102 | ); 103 | if (EFI_ERROR(Status)) { 104 | Print(L"Locate AtaPassThruProtocol Fail!\n"); 105 | return Status; 106 | } 107 | 108 | return Status; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /Application/HddId/HddId.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #define APP_VERSION L"v0.1" 5 | 6 | #define MAX_SUPPORT_CONTROLLER 2 7 | #define MAX_SUPPORT_DRIVES 6 8 | 9 | #define MAX_SUPPORT_PORTS 10 //support 10 ports implemented 10 | 11 | 12 | /*base addres offsets*/ 13 | #define PRIMARY_CMD_BASEADDR 0x10 14 | #define PRIMARY_CTRL_BASEADDR 0x14 15 | #define SECONDARY_CMD_BASEADDR 0x18 16 | #define SECONDARY_CTRL_BASEADDR 0x1C 17 | /*Legacy mode base addresses*/ 18 | #define LEGACY_PRIMARY_CMD_BASEADDR 0x1F0 19 | #define LEGACY_PRIMARY_CTRL_BASEADDR 0x3F4 //0x3F6 - 2 for compatible with native mode base address 20 | #define LEGACY_SECONDARY_CMD_BASEADDR 0x170 21 | #define LEGACY_SECONDARY_CTRL_BASEADDR 0x374 //0x376 - 2 22 | 23 | /* port offsets */ 24 | #define ATA_REG_DATA 0x00 25 | #define ATA_REG_ERROR 0x01 26 | #define ATA_REG_FEATURES 0x01 27 | #define ATA_REG_SECCOUNT 0x02 28 | #define ATA_REG_LBA_LOW 0x03 29 | #define ATA_REG_LBA_MED 0x04 30 | #define ATA_REG_LBA_HIGH 0x05 31 | #define ATA_REG_HDDEVSEL 0x06 32 | #define ATA_REG_COMMAND 0x07 33 | #define ATA_REG_STATUS 0x07 34 | #define ATA_REG_LBA3 0x03 35 | #define ATA_REG_LBA4 0x04 36 | #define ATA_REG_LBA5 0x05 37 | 38 | #define ATA_REG_CONTROL 0x02 39 | #define ATA_REG_ALTSTATUS 0x02 40 | #define ATA_REG_DEVADDRESS 0x0D 41 | 42 | #define ATA_REG_BMICOM 0x00 43 | #define ATA_REG_BMISTA 0x02 44 | #define ATA_REG_BMIDTP 0x04 45 | 46 | /* status */ 47 | #define ATA_SR_BSY 0x80 48 | #define ATA_SR_DRDY 0x40 49 | #define ATA_SR_DF 0x20 50 | #define ATA_SR_DSC 0x10 51 | #define ATA_SR_DRQ 0x08 52 | #define ATA_SR_CORR 0x04 53 | #define ATA_SR_IDX 0x02 54 | #define ATA_SR_ERR 0x01 55 | 56 | /* features/errors port */ 57 | #define ATA_ER_BBK 0x80 58 | #define ATA_ER_UNC 0x40 59 | #define ATA_ER_MC 0x20 60 | #define ATA_ER_IDNF 0x10 61 | #define ATA_ER_MCR 0x08 62 | #define ATA_ER_ABRT 0x04 63 | #define ATA_ER_TK0NF 0x02 64 | #define ATA_ER_AMNF 0x01 65 | 66 | /* command port */ 67 | #define ATA_CMD_READ_PIO 0x20 68 | #define ATA_CMD_READ_PIO_EXT 0x24 69 | #define ATA_CMD_READ_DMA 0xC8 70 | #define ATA_CMD_READ_DMA_EXT 0x25 71 | #define ATA_CMD_WRITE_PIO 0x30 72 | #define ATA_CMD_WRITE_PIO_EXT 0x34 73 | #define ATA_CMD_WRITE_DMA 0xCA 74 | #define ATA_CMD_WRITE_DMA_EXT 0x35 75 | #define ATA_CMD_CACHE_FLUSH 0xE7 76 | #define ATA_CMD_CACHE_FLUSH_EXT 0xEA 77 | #define ATA_CMD_PACKET 0xA0 78 | #define ATA_CMD_IDENTIFY_PACKET 0xA1 79 | #define ATA_CMD_IDENTIFY 0xEC 80 | #define ATAPI_CMD_READ 0xA8 81 | #define ATAPI_CMD_EJECT 0x1B 82 | 83 | /* ident space */ 84 | #define ATA_IDENT_DEVICETYPE 0 85 | #define ATA_IDENT_CYLINDERS 2 86 | #define ATA_IDENT_HEADS 6 87 | #define ATA_IDENT_SECTORS 12 88 | #define ATA_IDENT_SERIAL 20 89 | #define ATA_IDENT_MODEL 54 90 | #define ATA_IDENT_CAPABILITIES 98 91 | #define ATA_IDENT_FIELDVALID 106 92 | #define ATA_IDENT_MAX_LBA 120 93 | #define ATA_IDENT_COMMANDSETS 164 94 | #define ATA_IDENT_MAX_LBA_EXT 200 95 | 96 | /* control port */ 97 | #define ATA_CTRL_NIEN 0x02 98 | #define ATA_CTRL_SRST 0x04 99 | #define ATA_CTRL_HOB 0x08 100 | 101 | /* interfaces */ 102 | #define IDE_ATA 0x00 103 | #define IDE_ATAPI 0x01 104 | 105 | /* disks */ 106 | #define ATA_MASTER 0xA0 107 | #define ATA_SLAVE 0xB0 108 | 109 | /* channels */ 110 | #define ATA_PRIMARY 0x00 111 | #define ATA_SECONDARY 0x01 112 | 113 | /* direcctions */ 114 | #define ATA_READ 0x00 115 | #define ATA_WRITE 0x01 116 | 117 | 118 | typedef enum { 119 | IDE_CONTROLLER, 120 | SATA_AHCI_1, 121 | UNKNOWN_TYPE=99 122 | } EFI_MASS_STORAGE_TYPE; 123 | 124 | typedef struct 125 | { 126 | UINT32 BasePort; 127 | UINT32 ContrlPort; 128 | UINT16 SelDrive; //Master or Slave, value should be A0B0, A000, 00B0 129 | BOOLEAN Present; 130 | UINT8 Channel; //Primary or Secondary 131 | }EFI_IDE_DEVICES; 132 | 133 | typedef struct 134 | { 135 | UINT64 ATA_CONTROLLER_ADDRESS[MAX_SUPPORT_CONTROLLER]; //MAX support 5 IDE/AHCI contoller 136 | EFI_MASS_STORAGE_TYPE ATATypte; 137 | EFI_IDE_DEVICES IDE_DEVICES[MAX_SUPPORT_DRIVES]; 138 | }EFI_ATA_DEVICES; 139 | 140 | 141 | -------------------------------------------------------------------------------- /Application/HddId/HddId.inf: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Defines] 4 | INF_VERSION = 0x00010006 5 | BASE_NAME = HddId 6 | FILE_GUID = 893FE54D-395A-4ff5-AB56-547AC0CC5584 7 | MODULE_TYPE = UEFI_APPLICATION 8 | VERSION_STRING = 1.0 9 | ENTRY_POINT = ShellCEntryLib 10 | 11 | # 12 | # The following information is for reference only and not required by the build tools. 13 | # 14 | # VALID_ARCHITECTURES = IA32 X64 IPF EBC 15 | # 16 | 17 | [Sources] 18 | HddId.c 19 | HddId.h 20 | Misc.c 21 | Misc.h 22 | 23 | [Packages] 24 | MdePkg/MdePkg.dec 25 | MdeModulePkg/MdeModulePkg.dec 26 | ShellPkg/ShellPkg.dec 27 | MyPkg/MyPkg.dec 28 | 29 | [LibraryClasses] 30 | UefiApplicationEntryPoint 31 | UefiLib 32 | ShellCEntryLib 33 | PciLib 34 | AppFrameWorkLib 35 | AppCommonLib 36 | 37 | [Protocols] 38 | gEfiPciRootBridgeIoProtocolGuid 39 | gEfiAtaPassThruProtocolGuid 40 | gEfiPciIoProtocolGuid -------------------------------------------------------------------------------- /Application/HddId/Misc.c: -------------------------------------------------------------------------------- 1 | #include "Misc.h" 2 | #include 3 | #include 4 | 5 | extern EFI_APP_FRAMEWORK_TABLE gFT; 6 | 7 | EFI_STATUS 8 | Print_Help( 9 | ) 10 | { 11 | Print(L"HDD/ODD Identify. Copyright@2014. Version: %s\n", APP_VERSION); 12 | Print(L"Print ATA/ATAPI devices identify data, support AHCI and IDE controller.\n"); 13 | Print(L"Usage:\n"); 14 | Print(L"-h/-H/-? Print help\n"); 15 | 16 | return EFI_SUCCESS; 17 | } 18 | 19 | VOID 20 | PrintPCIAdress(UINT64 PCI_ADDRESS) 21 | { 22 | UINT8 BUS, DEV, FUNC; 23 | /* 24 | PCI_LIB_ADDRESS(Bus,Device,Function,Register) \ 25 | (((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) 26 | */ 27 | BUS = (UINT8)(PCI_ADDRESS >> 20)&0xFF; 28 | DEV = (UINT8)(PCI_ADDRESS >> 15)&0x1F; 29 | FUNC = (UINT8)(PCI_ADDRESS >> 12)&0x07; 30 | Print(L"BUS:%d DEV:%d FUNC:%d",BUS, DEV, FUNC); 31 | 32 | } 33 | 34 | EFI_STATUS 35 | hdd_wait_status(UINT32 idePort) 36 | { 37 | EFI_STATUS Status; 38 | UINT8 atasts; 39 | int i; 40 | 41 | Status = EFI_SUCCESS; 42 | 43 | for (i = 0; i < 1000; i++) { 44 | atasts = IoRead8(idePort+ATA_REG_STATUS); 45 | if ((atasts & (ATA_SR_BSY | ATA_SR_DRQ)) == ATA_SR_DRQ) 46 | return EFI_SUCCESS; 47 | if (atasts & (ATA_SR_ERR | ATA_SR_DF)) 48 | Status = EFI_DEVICE_ERROR; 49 | if (!atasts) 50 | Status = EFI_NOT_READY; 51 | 52 | gBS->Stall(100); 53 | } 54 | 55 | return Status; 56 | } 57 | 58 | EFI_STATUS 59 | GET_IDE_BaseAddress( 60 | EFI_ATA_DEVICES *IDE_Device 61 | ) 62 | { 63 | EFI_STATUS Status; 64 | UINT8 ctlr; 65 | UINT8 tmpval; 66 | UINT8 Count = 0; 67 | UINT64 IDE_PCI_ADDRESS; 68 | 69 | Status = EFI_SUCCESS; 70 | //init 71 | ZeroMem(IDE_Device->IDE_DEVICES,sizeof(EFI_IDE_DEVICES)*MAX_SUPPORT_DRIVES); 72 | 73 | for (ctlr = 0; ctlr < MAX_SUPPORT_CONTROLLER; ctlr++){ 74 | IDE_PCI_ADDRESS = IDE_Device->ATA_CONTROLLER_ADDRESS[ctlr]; 75 | if ( IDE_PCI_ADDRESS!= 0) { 76 | //1. check PCI config offset 0x09 Programming Interface Register, Legacy mode 0 or Native mode 1 77 | // bit0 for Primary mode native enable, bit2 for Secondary mode native enable 78 | // Note: PNE and SNE must be set by simultaneously, also in theory these bits can be programmed separately but HW not support!! 79 | // so we just need to check PNE here 80 | tmpval = PciRead8((UINTN)IDE_PCI_ADDRESS + 0x09); 81 | if (tmpval&BIT0){ 82 | // if in native PCI mode, get base port and control port in regs offset 0x10~0x1F 83 | IDE_Device->IDE_DEVICES[Count].Channel = ATA_PRIMARY; 84 | //Primary cmd base address 0x10 and not 0x07 85 | IDE_Device->IDE_DEVICES[Count].BasePort = (PciRead32((UINTN)IDE_PCI_ADDRESS + PRIMARY_CMD_BASEADDR)&(~0x07)); 86 | //Primary control base address 0x14 and not 0x03 87 | IDE_Device->IDE_DEVICES[Count].ContrlPort = (PciRead32((UINTN)IDE_PCI_ADDRESS + PRIMARY_CTRL_BASEADDR)&(~0x03)); 88 | Count++; 89 | 90 | IDE_Device->IDE_DEVICES[Count].Channel = ATA_SECONDARY; 91 | //Sencondary cmd base address 0x18 and not 0x07 92 | IDE_Device->IDE_DEVICES[Count].BasePort = (PciRead32((UINTN)IDE_PCI_ADDRESS + SECONDARY_CMD_BASEADDR)&(~0x07)); 93 | //Sencondary control base address 0x1C and not 0x03 94 | IDE_Device->IDE_DEVICES[Count].ContrlPort = (PciRead32((UINTN)IDE_PCI_ADDRESS + SECONDARY_CTRL_BASEADDR)&(~0x03)); 95 | Count++; 96 | } 97 | else{ 98 | // if in legacy PCI mode, get base port and control port is fixed 99 | // Primary 0x1F0~0x1F7, Primary ctrl 0x3F6; Secondary 0x170~0x176, Secondary ctrl 0x376 100 | IDE_Device->IDE_DEVICES[Count].Channel = ATA_PRIMARY; 101 | //Primary cmd base address 0x1F0 102 | IDE_Device->IDE_DEVICES[Count].BasePort = LEGACY_PRIMARY_CMD_BASEADDR; 103 | //Primary control base address 0x14 and not 0x03 104 | IDE_Device->IDE_DEVICES[Count].ContrlPort = LEGACY_PRIMARY_CTRL_BASEADDR; 105 | Count++; 106 | 107 | IDE_Device->IDE_DEVICES[Count].Channel = ATA_SECONDARY; 108 | //Sencondary cmd base address 0x18 and not 0x0E 109 | IDE_Device->IDE_DEVICES[Count].BasePort = LEGACY_SECONDARY_CMD_BASEADDR; 110 | //Sencondary control base address 0x1C and not 0x03 111 | IDE_Device->IDE_DEVICES[Count].ContrlPort = LEGACY_SECONDARY_CTRL_BASEADDR; 112 | Count++; 113 | } 114 | 115 | } 116 | } 117 | 118 | //debug 119 | /* if (DEBUG_SWITCH==2){ 120 | do{ 121 | Print(L"\nIDE Device %d: base:%x Control:%x Channel:%x",Count, IDE_Device->IDE_DEVICES[Count].BasePort, 122 | IDE_Device->IDE_DEVICES[Count].ContrlPort, 123 | IDE_Device->IDE_DEVICES[Count].Channel); 124 | }while(Count--); 125 | }*/ 126 | return Status; 127 | } 128 | 129 | EFI_STATUS 130 | DETECT_IDE_DEVICES( 131 | EFI_ATA_DEVICES *IDE_Device 132 | ) 133 | { 134 | EFI_STATUS Status; 135 | UINT8 i; 136 | UINT32 basePort; 137 | 138 | for (i = 0; i<= MAX_SUPPORT_DRIVES; i++){ 139 | basePort = IDE_Device->IDE_DEVICES[i].BasePort; 140 | if( basePort == 0) 141 | continue; 142 | //init detect as no devices 143 | IDE_Device->IDE_DEVICES[i].SelDrive = 0; 144 | IDE_Device->IDE_DEVICES[i].Present = FALSE; 145 | 146 | //write offset 0x06 with value 0xA0 and 0xB0 to detect devices 147 | //check offset 0x07 not 0 may need to modify, i found the value should be 0x50 if devices attached.(which means DSC&DRDY) 148 | IoWrite8(basePort + ATA_REG_HDDEVSEL, ATA_MASTER); 149 | Status = hdd_wait_status(basePort); 150 | if (!EFI_ERROR(Status)){ 151 | if (IoRead8(basePort + ATA_REG_HDDEVSEL) == ATA_MASTER) 152 | { 153 | IDE_Device->IDE_DEVICES[i].SelDrive |= (ATA_MASTER << 8); 154 | IDE_Device->IDE_DEVICES[i].Present = TRUE; 155 | } 156 | } 157 | //check Slave channel 158 | IoWrite8(basePort + ATA_REG_HDDEVSEL, ATA_SLAVE); 159 | Status = hdd_wait_status(basePort); 160 | if (!EFI_ERROR(Status)){ 161 | if (IoRead8(basePort + ATA_REG_HDDEVSEL) == ATA_SLAVE) 162 | { 163 | IDE_Device->IDE_DEVICES[i].SelDrive |= ATA_SLAVE; 164 | IDE_Device->IDE_DEVICES[i].Present = TRUE; 165 | } 166 | } 167 | } 168 | 169 | return EFI_SUCCESS; 170 | } 171 | 172 | EFI_STATUS 173 | DetectATAController( 174 | EFI_ATA_DEVICES *ATADevice 175 | ) 176 | { 177 | UINT8 tmpinterface; 178 | EFI_STATUS Status = EFI_SUCCESS; 179 | BOOLEAN Found; 180 | 181 | ATADevice->ATATypte = UNKNOWN_TYPE; 182 | ZeroMem(ATADevice->ATA_CONTROLLER_ADDRESS, sizeof(UINT64)*MAX_SUPPORT_CONTROLLER); 183 | 184 | //detect AHCI controller 185 | tmpinterface = 0x01; 186 | Found = AppProbePCIByClassCode(0x01, 0x06, &tmpinterface, ATADevice->ATA_CONTROLLER_ADDRESS); 187 | 188 | if (!Found){ 189 | //detect IDE controller 190 | Found = AppProbePCIByClassCode(0x01,0x01, 0x00, ATADevice->ATA_CONTROLLER_ADDRESS); 191 | if (Found){ 192 | ATADevice->ATATypte = IDE_CONTROLLER; 193 | GET_IDE_BaseAddress(ATADevice); 194 | DETECT_IDE_DEVICES(ATADevice); 195 | } 196 | }else{ 197 | ATADevice->ATATypte = SATA_AHCI_1; 198 | } 199 | 200 | return Status; 201 | } 202 | 203 | 204 | EFI_STATUS 205 | HDD_Reset(EFI_IDE_DEVICES IDE_Device) 206 | { 207 | EFI_STATUS Status; 208 | //ide reset 209 | IoWrite8(IDE_Device.ContrlPort + ATA_REG_CONTROL, 0x04); 210 | gBS->Stall(500); 211 | IoWrite8(IDE_Device.ContrlPort + ATA_REG_CONTROL, 0x02); 212 | gBS->Stall(2000); 213 | Status = hdd_wait_status(IDE_Device.BasePort); 214 | 215 | return Status; 216 | 217 | } 218 | 219 | EFI_STATUS 220 | IDE_Identify_Cmd( 221 | EFI_IDE_DEVICES IDE_Device, 222 | UINT8 Drive, 223 | UINT8 ATA_CMD 224 | ) 225 | { 226 | EFI_STATUS Status; 227 | 228 | Status = HDD_Reset(IDE_Device); 229 | if(EFI_ERROR(Status)){ 230 | return Status; 231 | } 232 | //hdd select 233 | IoWrite8(IDE_Device.BasePort + ATA_REG_HDDEVSEL, Drive); 234 | 235 | gBS->Stall(500); 236 | //clear 2~5 237 | IoWrite8(IDE_Device.BasePort + ATA_REG_SECCOUNT, 0); 238 | gBS->Stall(500); 239 | IoWrite8(IDE_Device.BasePort + ATA_REG_LBA_LOW, 0); 240 | gBS->Stall(500); 241 | IoWrite8(IDE_Device.BasePort + ATA_REG_LBA_MED, 0); 242 | gBS->Stall(500); 243 | IoWrite8(IDE_Device.BasePort + ATA_REG_LBA_HIGH, 0); 244 | gBS->Stall(500); 245 | 246 | //send identify cmd 247 | IoWrite8(IDE_Device.BasePort + ATA_REG_COMMAND, ATA_CMD); 248 | gBS->Stall(1000); 249 | if (ATA_CMD == ATAPI_CMD_IDENTIFY) 250 | gBS->Stall(1000); 251 | 252 | Status = hdd_wait_status(IDE_Device.BasePort); 253 | 254 | return Status; 255 | 256 | } 257 | 258 | EFI_STATUS 259 | SENT_IDE_Identify( 260 | EFI_IDE_DEVICES IDE_Device, 261 | UINT8 Drive, //Master or Slave 262 | UINT16 *IdentyBufferWORD 263 | ) 264 | { 265 | EFI_STATUS Status; 266 | UINTN i; 267 | Status = EFI_SUCCESS; 268 | ZeroMem(IdentyBufferWORD, 256*sizeof(UINT16)); 269 | 270 | Status = IDE_Identify_Cmd(IDE_Device,Drive,ATA_CMD_IDENTIFY); 271 | 272 | //check device error is kind of important here, because of found some AMD controller accept BYTE read data 273 | //if not check device error, may miss a WORD of identify data when read HDD on AMD controller 274 | if (Status == EFI_DEVICE_ERROR){ 275 | if (IoRead8(IDE_Device.BasePort) == 0x14){ 276 | Status = IDE_Identify_Cmd(IDE_Device,Drive,ATAPI_CMD_IDENTIFY); 277 | } 278 | } 279 | 280 | if ( !EFI_ERROR(Status)){ 281 | for (i = 0; i<=0xFF; i++){ 282 | IdentyBufferWORD[i] = IoRead16(IDE_Device.BasePort); 283 | } 284 | } 285 | return Status; 286 | 287 | } 288 | 289 | EFI_STATUS 290 | IDE_HDD_Identify( 291 | EFI_ATA_DEVICES *ATA_Device, 292 | UINT16 *IdentyBufferWORD 293 | ) 294 | { 295 | EFI_STATUS Status; 296 | UINT8 i; 297 | UINT64 IDE_PCI_ADDRESS; 298 | Status = EFI_SUCCESS; 299 | 300 | //print IDE controller address: 301 | for (i = 0; i < MAX_SUPPORT_CONTROLLER; i++){ 302 | IDE_PCI_ADDRESS = ATA_Device->ATA_CONTROLLER_ADDRESS[i]; 303 | if (IDE_PCI_ADDRESS != 0){ 304 | Print(L"\nIDE controller "); 305 | PrintPCIAdress(IDE_PCI_ADDRESS); 306 | } 307 | } 308 | Print(L"\n"); 309 | for (i = 0; i< MAX_SUPPORT_DRIVES; i++){ 310 | if (ATA_Device->IDE_DEVICES[i].Present){ 311 | if ((ATA_Device->IDE_DEVICES[i].SelDrive & 0xFF00) == 0xA000){ 312 | Status = SENT_IDE_Identify(ATA_Device->IDE_DEVICES[i], 0xA0, IdentyBufferWORD); 313 | if (!EFI_ERROR(Status)){ 314 | (ATA_Device->IDE_DEVICES[i].Channel == ATA_PRIMARY)?Print(L"\nPrimary "):Print(L"\nSecondary "); 315 | Print(L"Master"); 316 | AppPrintBuffer(IdentyBufferWORD); 317 | } 318 | } 319 | if ((ATA_Device->IDE_DEVICES[i].SelDrive & 0x00FF) == 0x00B0){ 320 | Status = SENT_IDE_Identify(ATA_Device->IDE_DEVICES[i], 0xB0, IdentyBufferWORD); 321 | if (!EFI_ERROR(Status)){ 322 | (ATA_Device->IDE_DEVICES[i].Channel == ATA_PRIMARY)?Print(L"\nPrimary "):Print(L"\nSecondary "); 323 | Print(L"Slave"); 324 | AppPrintBuffer(IdentyBufferWORD); 325 | } 326 | } 327 | } 328 | }//end for 329 | 330 | return Status; 331 | } 332 | 333 | EFI_STATUS 334 | AHCI_HDD_Identify( 335 | UINT64 AHCI_PCI_ADDRESS, 336 | UINT8 *IdentyBuffer512B 337 | ) 338 | { 339 | EFI_STATUS Status=EFI_SUCCESS; 340 | UINT8 PortImplement; 341 | UINT16 Port; 342 | UINT32 AHCIBAR; 343 | EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PCIrb; 344 | EFI_ATA_PASS_THRU_PROTOCOL *ATApt; 345 | 346 | PCIrb = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *)gFT.PROTOCOL1; 347 | ATApt = (EFI_ATA_PASS_THRU_PROTOCOL *)gFT.PROTOCOL2; 348 | 349 | //get AHCI bar in offset 24h~27h 350 | AHCIBAR = PciRead32 ((UINTN)AHCI_PCI_ADDRESS+0x24); 351 | Print(L"AHCI controller 1.0 at "); 352 | PrintPCIAdress(AHCI_PCI_ADDRESS); 353 | 354 | Print(L"\nAHCI bar = %x \n", AHCIBAR); 355 | 356 | Status = PCIrb->Mem.Read(PCIrb, EfiPciWidthUint8, \ 357 | (UINT64)(UINTN)(AHCIBAR+0x0C), 1, &PortImplement); 358 | 359 | for (Port = 0; Port <= MAX_SUPPORT_PORTS; Port++){ 360 | if (PortImplement&1){ 361 | 362 | ZeroMem(IdentyBuffer512B, sizeof(512*sizeof(UINT8))); 363 | 364 | AppAhciIdentify(ATApt, Port, 0, IdentyBuffer512B); 365 | 366 | if (!EFI_ERROR(Status)){ 367 | Print(L"\n\nPort %d Identify data:\n", Port); 368 | AppPrintBuffer((UINT16 *)IdentyBuffer512B); 369 | } 370 | 371 | } 372 | PortImplement >>= 1; 373 | } 374 | return Status; 375 | } -------------------------------------------------------------------------------- /Application/HddId/Misc.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | //add below include for gST, gBS 8 | #include "Library/UefiBootServicesTableLib.h" 9 | //add for ZeroMem 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include "HddId.h" 20 | 21 | EFI_STATUS 22 | Print_Help( 23 | ); 24 | 25 | EFI_STATUS 26 | DetectATAController( 27 | EFI_ATA_DEVICES *ATADevice 28 | ); 29 | 30 | EFI_STATUS 31 | AHCI_HDD_Identify( 32 | UINT64 AHCI_PCI_ADDRESS, 33 | UINT8 *IdentyBuffer512B 34 | ); 35 | 36 | EFI_STATUS 37 | IDE_HDD_Identify( 38 | EFI_ATA_DEVICES *ATA_Device, 39 | UINT16 *IdentyBufferWORD 40 | ); -------------------------------------------------------------------------------- /Application/HiiMenu/HiiForm1Strings.uni: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kurtqiao/MyPkg/76a405a7a6a9c62e1ce456045305ebda7c35928d/Application/HiiMenu/HiiForm1Strings.uni -------------------------------------------------------------------------------- /Application/HiiMenu/HiiForm1Vfr.vfr: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "HiiMenuGUIDs.h" 4 | 5 | formset 6 | guid = HII_MENU_FORM1_GUID, 7 | title = STRING_TOKEN(STR_HIIMENU_TITLE), 8 | help = STRING_TOKEN(STR_HIIMENU_HELP), 9 | 10 | form formid = 1, 11 | title = STRING_TOKEN(STR_HIIMENU_TITLE); 12 | 13 | goto 2, 14 | prompt = STRING_TOKEN(STR_HIIMENU_FORMID1_TITLE), 15 | help = STRING_TOKEN(STR_NULL_STRING); 16 | 17 | goto 3, 18 | prompt = STRING_TOKEN(STR_HIIMENU_FORMID2_TITLE), 19 | help = STRING_TOKEN(STR_NULL_STRING); 20 | endform; 21 | 22 | form formid = 2, 23 | title = STRING_TOKEN(STR_HIIMENU_FORMID1_TITLE); 24 | 25 | text 26 | help = STRING_TOKEN(STR_HIIMENU_ITEM1_HELP), 27 | text = STRING_TOKEN(STR_HIIMENU_ITEM1_TEXT), 28 | text = STRING_TOKEN(STR_NULL_STRING); 29 | 30 | endform; 31 | 32 | form formid = 3, 33 | title = STRING_TOKEN(STR_HIIMENU_FORMID2_TITLE); 34 | 35 | text 36 | help = STRING_TOKEN(STR_HIIMENU_ITEM2_HELP), 37 | text = STRING_TOKEN(STR_HIIMENU_ITEM2_TEXT); 38 | 39 | endform; 40 | endformset; -------------------------------------------------------------------------------- /Application/HiiMenu/HiiMenu.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "HiiMenu.h" 4 | #include "HiiMenuGUIDs.h" 5 | 6 | EFI_GUID mHiiForm1Guid = HII_MENU_FORM1_GUID; 7 | 8 | EFI_STATUS 9 | EFIAPI 10 | ShellAppMain ( 11 | IN UINTN Argc, 12 | IN CHAR16 **Argv 13 | ) 14 | { 15 | EFI_STATUS Status; 16 | EFI_HII_HANDLE HiiHandle; 17 | EFI_HII_DATABASE_PROTOCOL *HiiDatabase; 18 | EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; 19 | 20 | // 21 | // Locate Hii Database protocol 22 | // 23 | Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase); 24 | if (EFI_ERROR (Status)) { 25 | return Status; 26 | } 27 | // 28 | // Locate Formbrowser2 protocol 29 | // 30 | Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); 31 | if (EFI_ERROR (Status)) { 32 | return Status; 33 | } 34 | // 35 | // Publish our HII data 36 | // 37 | HiiHandle = HiiAddPackages ( 38 | &mHiiForm1Guid, 39 | NULL, 40 | HiiMenuStrings, 41 | HiiForm1VfrBin, 42 | NULL 43 | ); 44 | if (HiiHandle == NULL) { 45 | return EFI_OUT_OF_RESOURCES; 46 | } 47 | 48 | //call SendForm to show 49 | Status = FormBrowser2->SendForm ( 50 | FormBrowser2, 51 | &HiiHandle, 52 | 1, //handle count 53 | NULL, //formsetguid optional 54 | 0, //form id optional 55 | NULL, //screen optional 56 | NULL //action request optional 57 | ); 58 | HiiRemovePackages (HiiHandle); 59 | 60 | return Status; 61 | } -------------------------------------------------------------------------------- /Application/HiiMenu/HiiMenu.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | //below extern will be built out by VFR compiler. 11 | extern unsigned char HiiMenuStrings[]; 12 | extern UINT8 HiiForm1VfrBin[]; -------------------------------------------------------------------------------- /Application/HiiMenu/HiiMenu.inf: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Defines] 4 | INF_VERSION = 0x00010006 5 | BASE_NAME = HiiMenu 6 | FILE_GUID = C5BFE29F-0524-4566-B767-B0C9075A30BE 7 | MODULE_TYPE = UEFI_APPLICATION 8 | VERSION_STRING = 1.0 9 | ENTRY_POINT = ShellCEntryLib 10 | 11 | # 12 | # The following information is for reference only and not required by the build tools. 13 | # 14 | # VALID_ARCHITECTURES = IA32 X64 IPF EBC 15 | # 16 | 17 | [Sources] 18 | HiiMenu.c 19 | HiiMenu.h 20 | HiiMenuGUIDs.h 21 | HiiMenu.inf 22 | HiiForm1Vfr.vfr 23 | HiiForm1Strings.uni 24 | 25 | [Packages] 26 | MdePkg/MdePkg.dec 27 | MdeModulePkg/MdeModulePkg.dec 28 | ShellPkg/ShellPkg.dec 29 | MyPkg/MyPkg.dec 30 | 31 | [LibraryClasses] 32 | UefiApplicationEntryPoint 33 | UefiLib 34 | ShellCEntryLib 35 | HiiLib 36 | 37 | [Protocols] 38 | gEfiHiiDatabaseProtocolGuid 39 | gEfiFormBrowser2ProtocolGuid -------------------------------------------------------------------------------- /Application/HiiMenu/HiiMenuGUIDs.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | // {EF2ACC91-7B50-4ab9-AB67-2B04F8BC135E} 4 | #define HII_MENU_FORM1_GUID \ 5 | { 0xef2acc91, 0x7b50, 0x4ab9, { 0xab, 0x67, 0x2b, 0x4, 0xf8, 0xbc, 0x13, 0x5e } } -------------------------------------------------------------------------------- /Application/bootmgr/bootmgr.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * boot managerr EFI variables 4 | * 5 | * 6 | ***************************************************************************/ 7 | #include 8 | #include 9 | #include 10 | #include "Library/UefiRuntimeServicesTableLib.h" 11 | #include "Guid/GlobalVariable.h" 12 | #include 13 | 14 | typedef struct{ 15 | UINT16 bootnum; 16 | UINTN show_verbose : 1; 17 | UINTN set_bootorder : 1; 18 | UINTN : 1; 19 | UINTN usage : 1; 20 | }BOOTMGROPTS; 21 | 22 | BOOTMGROPTS opts={0}; 23 | 24 | VOID 25 | Usage() 26 | { 27 | Print(L"bootmgr ver 0.1\n"); 28 | Print(L"[-v] verbose display\n"); 29 | Print(L"[-s bootnum] set first boot\n" ); 30 | Print(L"[-h] help\n"); 31 | } 32 | 33 | BOOLEAN 34 | EFIAPI 35 | IsCharDigit ( 36 | IN CHAR16 Char 37 | ) 38 | { 39 | return (BOOLEAN) (Char >= L'0' && Char <= L'9')||(Char >= L'A' && Char <= L'F'); 40 | } 41 | 42 | //refer to IntelFrameworkPkg/Lib/GenericBdsLib/BdsMisc.c BdsLibGetVariableAndSize 43 | VOID * 44 | EFIAPI 45 | mGetVariable( 46 | IN CHAR16 *Name, 47 | IN EFI_GUID *VendorGuid, 48 | OUT UINTN *VariableSize, 49 | OUT UINT32 *Attr 50 | ) 51 | { 52 | EFI_STATUS Status; 53 | UINTN BufferSize; 54 | VOID *Buffer; 55 | 56 | Buffer = NULL; 57 | 58 | // 59 | // Pass in a zero size buffer to find the required buffer size. 60 | // 61 | BufferSize = 0; 62 | Status = gRT->GetVariable (Name, VendorGuid, Attr, &BufferSize, Buffer); 63 | if (Status == EFI_BUFFER_TOO_SMALL) { 64 | // 65 | // Allocate the buffer to return 66 | // 67 | Buffer = AllocateZeroPool (BufferSize); 68 | if (Buffer == NULL) { 69 | *VariableSize = 0; 70 | return NULL; 71 | } 72 | // 73 | // Read variable into the allocated buffer. 74 | // 75 | Status = gRT->GetVariable (Name, VendorGuid, Attr, &BufferSize, Buffer); 76 | if (EFI_ERROR (Status)) { 77 | FreePool (Buffer); 78 | BufferSize = 0; 79 | Buffer = NULL; 80 | } 81 | } 82 | 83 | *VariableSize = BufferSize; 84 | return Buffer; 85 | } 86 | VOID 87 | ParseOpt( 88 | UINTN Argc, 89 | CHAR16 **Argv 90 | ) 91 | { 92 | UINTN Index; 93 | 94 | for (Index = 1; Index < Argc; Index ++) { 95 | if ((Argv[Index][0] != L'-') || (Argv[Index][2] != L'\0')) { 96 | return ; 97 | } 98 | 99 | switch (Argv[Index][1]) { 100 | case L'v': 101 | opts.show_verbose = 1; 102 | break; 103 | case L's': 104 | opts.set_bootorder = 1; 105 | opts.bootnum = (UINT16)StrHexToUintn(Argv[Index+1]); 106 | break; 107 | case L'h': 108 | case L'H': 109 | case L'?': 110 | opts.usage = 1; 111 | break; 112 | 113 | default: 114 | break; 115 | } 116 | } 117 | } 118 | 119 | EFI_STATUS 120 | EFIAPI 121 | ShellAppMain ( 122 | IN UINTN Argc, 123 | IN CHAR16 **Argv 124 | ) 125 | { 126 | EFI_STATUS Status; 127 | UINT16 *BootVariable; 128 | UINTN BootVariableSize; 129 | UINT16 LDAttr; 130 | CHAR16 *Name; 131 | UINTN NewNameSize; 132 | UINTN NameSize; 133 | UINTN i; 134 | UINT32 Attr; 135 | EFI_GUID VarGuid; 136 | 137 | 138 | ParseOpt(Argc, Argv); 139 | 140 | //------------Usage----------------------- 141 | if (opts.usage){ 142 | Usage(); 143 | return EFI_SUCCESS; 144 | } 145 | //----------Set BootOrder----------------- 146 | if (opts.set_bootorder){ 147 | BootVariable = mGetVariable(L"BootOrder", &gEfiGlobalVariableGuid, &BootVariableSize, &Attr); 148 | BootVariable[0]=opts.bootnum; 149 | Status = gRT->SetVariable(L"BootOrder", &gEfiGlobalVariableGuid, Attr, BootVariableSize, BootVariable); 150 | if (!EFI_ERROR(Status)) 151 | Print(L"Set first boot to Boot%04x\n", opts.bootnum); 152 | return Status; 153 | } 154 | 155 | 156 | //----------Show Boot UEFI variables-------- 157 | //get BootCurrent 158 | BootVariable = mGetVariable(L"BootCurrent", &gEfiGlobalVariableGuid, &BootVariableSize, NULL); 159 | if (BootVariable != NULL) 160 | Print(L"BootCurrent: %04x\n", *BootVariable); 161 | //get BootOrder 162 | BootVariable = mGetVariable(L"BootOrder", &gEfiGlobalVariableGuid, &BootVariableSize, &Attr); 163 | if (BootVariable != NULL){ 164 | Print(L"BootOrder: "); 165 | for(i=0; i<(BootVariableSize/2); i++){ 166 | Print(L" %04x ",BootVariable[i]); 167 | } 168 | Print(L"\n"); 169 | } 170 | 171 | //Print all BOOT#### Load Options 172 | NameSize = sizeof(CHAR16); 173 | Name = AllocateZeroPool(NameSize); 174 | for (i=0; ;i++ ){ 175 | NewNameSize = NameSize; 176 | //search all EFI variables 177 | Status = gRT->GetNextVariableName (&NewNameSize, Name, &VarGuid); 178 | if (Status == EFI_BUFFER_TOO_SMALL) { 179 | Name = ReallocatePool (NameSize, NewNameSize, Name); 180 | Status = gRT->GetNextVariableName (&NewNameSize, Name, &VarGuid); 181 | NameSize = NewNameSize; 182 | } 183 | // 184 | if (Status == EFI_NOT_FOUND) { 185 | break; 186 | } 187 | //skip if not Global variable 188 | if (!CompareGuid(&VarGuid, &gEfiGlobalVariableGuid)) 189 | continue; 190 | //check BOOT#### variable 191 | if(!StrnCmp(Name, L"Boot", 4) && 192 | IsCharDigit(Name[4]) && IsCharDigit(Name[5]) && 193 | IsCharDigit(Name[6]) && IsCharDigit(Name[7])) 194 | { 195 | Print(L"%s:", Name); 196 | //get BOOT#### 197 | BootVariable = mGetVariable(Name, &gEfiGlobalVariableGuid, &BootVariableSize, NULL); 198 | //print attribute 199 | LDAttr = BootVariable[0]; 200 | if (opts.show_verbose){ 201 | i = 6; //for adjust display 202 | if (LDAttr == 0) 203 | Print(L"CB*", i--); //category boot 204 | if (LDAttr & 1) 205 | Print(L"A* ", i--); //active 206 | if (LDAttr & 2) 207 | Print(L"FR*", i--); //force reconnect 208 | if (LDAttr & 8) 209 | Print(L"H* ", i--); //hidden 210 | if (LDAttr & 0x100) 211 | Print(L"CA*", i--); //category app 212 | //Print(L"\n"); 213 | while (i--){ 214 | Print(L" "); 215 | } 216 | } 217 | //print EFI_LOAD_OPTION description 218 | Print(L" %s",(CHAR16 *)(BootVariable+3)); 219 | Print(L"\n"); 220 | 221 | } 222 | } 223 | 224 | return Status; 225 | } 226 | -------------------------------------------------------------------------------- /Application/bootmgr/bootmgr.inf: -------------------------------------------------------------------------------- 1 | [Defines] 2 | INF_VERSION = 0x00010006 3 | BASE_NAME = bootmgr 4 | FILE_GUID = AAC2EA6F-D4C8-4e43-996A-9CDB20742C86 5 | MODULE_TYPE = UEFI_APPLICATION 6 | VERSION_STRING = 0.1 7 | ENTRY_POINT = ShellCEntryLib 8 | 9 | # 10 | # VALID_ARCHITECTURES = IA32 X64 IPF 11 | # 12 | 13 | [Sources] 14 | bootmgr.c 15 | 16 | [Packages] 17 | ShellPkg/ShellPkg.dec 18 | MdePkg/MdePkg.dec 19 | MyPkg/MyPkg.dec 20 | # IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec 21 | 22 | [LibraryClasses] 23 | ShellCEntryLib 24 | # UefiApplicationEntryPoint 25 | UefiLib 26 | # GenericBdsLib 27 | 28 | 29 | [Guids] 30 | gEfiGlobalVariableGuid 31 | 32 | [Protocols] 33 | 34 | [BuildOptions] 35 | 36 | -------------------------------------------------------------------------------- /Application/ctest/ctest.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * ctest 4 | * 5 | * a test c program 6 | ***************************************************************************/ 7 | #include 8 | 9 | int main(void) 10 | { 11 | int a, b; 12 | a = 0; 13 | b = 0; 14 | printf("hello! C program in UEFI!\n"); 15 | printf("Test plus math, please input two number:"); 16 | scanf("%d %d", &a, &b); 17 | printf("%d + %d = %d\n", a, b, a+b); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /Application/ctest/ctest.inf: -------------------------------------------------------------------------------- 1 | [Defines] 2 | INF_VERSION = 0x00010006 3 | BASE_NAME = ctest 4 | FILE_GUID = C5845F1D-DC9F-4ccd-88F9-58C9E845ED76 5 | MODULE_TYPE = UEFI_APPLICATION 6 | VERSION_STRING = 0.1 7 | ENTRY_POINT = ShellCEntryLib 8 | 9 | # 10 | # VALID_ARCHITECTURES = IA32 X64 IPF 11 | # 12 | 13 | [Sources] 14 | ctest.c 15 | 16 | [Packages] 17 | StdLib/StdLib.dec 18 | ShellPkg/ShellPkg.dec 19 | MdePkg/MdePkg.dec 20 | MyPkg/MyPkg.dec 21 | 22 | [LibraryClasses] 23 | LibC 24 | LibStdio 25 | 26 | [Guids] 27 | 28 | [Protocols] 29 | 30 | [BuildOptions] 31 | # MSFT:*_*_*_CC_FLAGS = /Od /D_UEFI_ /DCURL_STATICLIB 32 | -------------------------------------------------------------------------------- /Application/mixbuild/MAKEFILE: -------------------------------------------------------------------------------- 1 | # makefile for open watcom wmake 2 | # wmake 3 | # wmake clean 4 | 5 | PROGRAM = mixtest 6 | ASM = iolib 7 | CC = wcc 8 | WA = wasm 9 | WL = wcl 10 | 11 | EXE = $(PROGRAM).exe 12 | SRC = $(PROGRAM).c 13 | OBJ = $(ASM).obj 14 | 15 | all: $(EXE) .SYMBOLIC 16 | 17 | $(EXE): $(OBJ) 18 | $(WL) -bt=dos $(SRC) $(OBJ) 19 | 20 | $(OBJ): $(ASM).asm 21 | $(WA) -ms $(ASM).asm 22 | 23 | clean: .SYMBOLIC 24 | del *.obj *.exe 25 | -------------------------------------------------------------------------------- /Application/mixbuild/iolib.asm: -------------------------------------------------------------------------------- 1 | ;Mixing Assembly and C 2 | ;https://courses.engr.illinois.edu/ece390/books/labmanual/c-prog-mixing.html 3 | 4 | ;https://msdn.microsoft.com/en-us/library/zthk2dkh(v=vs.80).aspx 5 | ;Integer: First 4 parameters – RCX, RDX, R8, R9. Others passed on stack. 6 | 7 | ;http://biosren.com/thread-6632-1-2.html 8 | ;RAX, RCX, RDX, R8, R9, R10, R11 are considered volatile and 9 | ;must be considered destroyed on function calls, so there is 10 | ;no reason to save them. 11 | ;First 4 parameters - RCX, RDX, R8, R9. Others passed on stack. 12 | ;The registers RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are 13 | ;considered nonvolatile and must be saved and restored by a 14 | ;function that uses them. 15 | 16 | .MODEL small 17 | .386 18 | 19 | PUBLIC _ADD_VAL 20 | PUBLIC _in_byte 21 | PUBLIC _out_byte 22 | .code 23 | 24 | _in_byte proc 25 | push bp 26 | mov bp, sp 27 | xor ax, ax 28 | mov dx, word ptr [bp+4] 29 | in al, dx 30 | out 0edh, al 31 | pop bp 32 | ret 33 | _in_byte endp 34 | 35 | _out_byte proc 36 | ;never push pop save dx, or will get wrong return value 37 | push bp 38 | mov bp, sp 39 | xor ax, ax 40 | mov dx, [bp+4] ;parameter 1, port 41 | mov ax, [bp+6] ;parameter 2, data 42 | out dx, al 43 | pop bp 44 | 45 | ret 46 | _out_byte endp 47 | 48 | _ADD_VAL proc 49 | push dx 50 | push bp 51 | mov bp, sp 52 | mov ax, [bp+4] 53 | mov bx, [bp+6] 54 | mov ax, bx 55 | pop bp 56 | pop dx 57 | ret 58 | _ADD_VAL endp 59 | 60 | END 61 | -------------------------------------------------------------------------------- /Application/mixbuild/mixtest.c: -------------------------------------------------------------------------------- 1 | /* 2 | mixtest 3 | demo how to create a common program, which could be bulit as dos app by 4 | open watcom c and shell app by uefi edk2 build env 5 | 6 | 1.DOS 16bit application: 7 | wasm -ms iolib.asm 8 | wcl -bt=dos mixtest.c iolib.obj 9 | 10 | 2. 64bit UEFI application: 11 | add mixtest.inf into MyPkg.dsc 12 | build -a X64 -p MyPkg\MyPkg.dsc -t VS2013x86 13 | 14 | support getopt(), refer to: edk2\AppPkg\Applications\OrderedCollectionTest 15 | */ 16 | 17 | 18 | #ifdef EFI_SPECIFICATION_VERSION 19 | #undef DOS_APP 20 | #pragma message ( "define uefi" ) 21 | #else 22 | #define DOS_APP 23 | #pragma message ( "define dos" ) 24 | #endif 25 | 26 | #include 27 | #include 28 | #include // getopt() 29 | 30 | #ifdef DOS_APP 31 | #include //basename() 32 | 33 | extern int cdecl ADD_VAL(int, int); 34 | extern unsigned char cdecl in_byte(int); 35 | extern void cdecl out_byte(int, int); 36 | #else 37 | #include 38 | 39 | unsigned char 40 | in_byte(int index) 41 | { 42 | return IoRead8(index); 43 | } 44 | 45 | void 46 | out_byte(UINT8 port, UINT8 data) 47 | { 48 | IoWrite8(port, data); 49 | } 50 | #endif 51 | 52 | 53 | typedef struct _action 54 | { 55 | unsigned char help :1; 56 | unsigned char shutdown :1; 57 | unsigned char reboot :1; 58 | unsigned char wakeup :1; 59 | }ACTION; 60 | 61 | int 62 | print_usage(char *prog_name, FILE *channel, int ret_val) 63 | { 64 | fprintf(channel, "\nusage: %s [-x | -x xxx | -x xxx]\n", prog_name); 65 | fprintf(channel, "Options\n"); 66 | fprintf(channel, "-x xx1\n"); 67 | fprintf(channel, "-x xxx parameter1 x xxx\n"); 68 | fprintf(channel, "-x xxx parameter2 x xxx\n"); 69 | return ret_val; 70 | } 71 | 72 | unsigned char read_cmos(unsigned char index) 73 | { 74 | unsigned char data; 75 | out_byte(0x70, index); 76 | data = in_byte(0x71); 77 | return data; 78 | 79 | } 80 | 81 | static int 82 | parsing_commands ( 83 | int argc, 84 | char **argv, 85 | ACTION *action 86 | ) 87 | { 88 | int option; 89 | 90 | while ((option = getopt (argc, argv, ":hst:w:")) !=-1) 91 | { 92 | switch(option) 93 | { 94 | default: 95 | // fprintf(stderr, "internal error: unknown case %c\n", optopt); 96 | return EXIT_FAILURE; 97 | 98 | #ifdef DOS_APP 99 | // Remove below when in edk2 build 100 | // The current "compatibility" getopt() implementation doesn't support optopt 101 | case '?': 102 | fprintf(stderr, "error: unknown option: -%c\n", optopt); 103 | break; 104 | case ':': 105 | fprintf(stderr, "error: missing argument for option -%c\n", optopt); 106 | break; 107 | #endif 108 | 109 | case 'h': 110 | action->help = 1; 111 | break; 112 | } 113 | } 114 | 115 | return 0; 116 | } 117 | 118 | int 119 | main(int argc, char * argv[]) 120 | { 121 | 122 | ACTION action = {0}; 123 | 124 | 125 | parsing_commands(argc, argv, &action); 126 | 127 | if (action.help) 128 | print_usage(basename(argv[0]), stderr, EXIT_SUCCESS); 129 | 130 | printf("read cmos value = %x\n", read_cmos(0) ); 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /Application/mixbuild/mixtest.inf: -------------------------------------------------------------------------------- 1 | [Defines] 2 | INF_VERSION = 0x00010006 3 | BASE_NAME = mixtest 4 | FILE_GUID = E1CF340C-51F0-411b-9CD4-64A366C9084D 5 | MODULE_TYPE = UEFI_APPLICATION 6 | VERSION_STRING = 0.1 7 | ENTRY_POINT = ShellCEntryLib 8 | 9 | # 10 | # VALID_ARCHITECTURES = IA32 X64 IPF 11 | # 12 | 13 | [Sources] 14 | mixtest.c 15 | 16 | [Packages] 17 | StdLib/StdLib.dec 18 | ShellPkg/ShellPkg.dec 19 | MdePkg/MdePkg.dec 20 | MyPkg/MyPkg.dec 21 | 22 | [LibraryClasses] 23 | LibC 24 | LibStdio 25 | IoLib 26 | 27 | [Guids] 28 | 29 | [Protocols] 30 | 31 | [BuildOptions] 32 | # MSFT:*_*_*_CC_FLAGS = /Od /D_UEFI_ /DCURL_STATICLIB 33 | -------------------------------------------------------------------------------- /Application/mixbuild/mk_mixtest.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM Build by Open Watcom C - C++ v1.9 3 | 4 | 5 | if exist iolib.obj del iolib.obj 6 | if exist mixtest.obj del mixtest.obj 7 | if exist mixtest.exe del mixtest.exe 8 | 9 | if "%1"=="clean" goto end 10 | 11 | wasm -ms iolib.asm 12 | wcl -bt=dos mixtest.c iolib.obj 13 | 14 | 15 | :end -------------------------------------------------------------------------------- /Application/pwcycle/pwcycle.c: -------------------------------------------------------------------------------- 1 | /* 2 | pwcycle utility 3 | build 4 | DOS version: wcl -bt=dos pwcycle.c 5 | UEFI version: add pwcycle.inf into MyPkg.dsc 6 | 7 | usage: pwcycle -s -t 10 -w 10 8 | -s shutdown 9 | -r reboot 10 | -t xx timeout xx seconds 11 | -w xx wakeup after xx secnods 12 | 13 | only support on intel platform, which assume PMBase address is 0x1800 14 | */ 15 | 16 | #ifdef EFI_SPECIFICATION_VERSION 17 | #undef DOS 18 | #pragma message ( "define uefi" ) 19 | #else 20 | #define DOS 21 | #pragma message ( "define dos" ) 22 | #endif 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef DOS 30 | #include 31 | #else 32 | #include 33 | #endif 34 | 35 | typedef unsigned char u8; 36 | typedef unsigned short u16; 37 | typedef unsigned int u32; 38 | typedef unsigned long long u64; 39 | 40 | #define PMBASE 0x1800 41 | 42 | #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) 43 | #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) 44 | 45 | 46 | enum{ 47 | RTC_SECONDS = 0x00, 48 | RTC_SECONDS_ALARM, 49 | RTC_MINUTES, 50 | RTC_MINUTES_ALARM, 51 | RTC_HOURS, 52 | RTC_HOURS_ALARM, 53 | RTC_DAY_OF_WEEK, 54 | RTC_DAY_OF_MONTH, 55 | RTC_MONTH, 56 | RTC_YEAR, 57 | RTC_STS_REG_A, 58 | RTC_STS_REG_B, 59 | RTC_STS_REG_C, 60 | RTC_STS_REG_D, 61 | CMOS_INDX = 0x70, 62 | CMOS_DATA = 0x71 63 | }; 64 | 65 | #ifdef DOS 66 | enum reg_bits 67 | { 68 | BIT0 = 1 << 0, 69 | BIT1 = 1 << 1, 70 | BIT2 = 1 << 2, 71 | BIT3 = 1 << 3, 72 | BIT4 = 1 << 4, 73 | BIT5 = 1 << 5, 74 | BIT6 = 1 << 6, 75 | BIT7 = 1 << 7 76 | }; 77 | #endif 78 | 79 | #define S5 BIT2|BIT3|BIT4 80 | 81 | enum 82 | { 83 | SHUTDOWN = BIT0, 84 | REBOOT = BIT1, 85 | SLP_EN = BIT5, 86 | WAKEUP = BIT7 87 | }; 88 | 89 | typedef struct _action 90 | { 91 | unsigned char help :1; 92 | unsigned char shutdown :1; 93 | unsigned char reboot :1; 94 | unsigned char wakeup :1; 95 | unsigned char error :1; 96 | }ACTION; 97 | 98 | typedef struct rtc_time 99 | { 100 | u8 tm_sec; 101 | u8 tm_sec_alarm; 102 | u8 tm_min; 103 | u8 tm_min_alarm; 104 | u8 tm_hour; 105 | u8 tm_hour_alram; 106 | u8 tm_day_of_week; 107 | u8 tm_day_of_month; 108 | u8 tm_month; 109 | u8 tm_year; 110 | u8 tm_sts_reg_a; 111 | u8 tm_sts_reg_b; 112 | u8 tm_sts_reg_c; 113 | u8 tm_sts_reg_d; 114 | }RTC_TIME; 115 | 116 | typedef struct _rtc_device 117 | { 118 | RTC_TIME rtc_time; 119 | void (*get_time)(RTC_TIME *); 120 | void (*set_alarm)(RTC_TIME *); 121 | void (*calc_alarm)(RTC_TIME *, u8 waketime); 122 | }RTC_DEVICE; 123 | 124 | #ifdef DOS 125 | u8 in_byte(u16 index) 126 | { 127 | u8 data=0; 128 | _asm 129 | { 130 | xor dx, dx 131 | mov dx, index 132 | in al, dx 133 | mov data, al 134 | }; 135 | return data; 136 | } 137 | 138 | void 139 | set_int_flag(int option) 140 | { 141 | if (option) 142 | _asm { sti }; 143 | else 144 | _asm { cli }; 145 | } 146 | void 147 | out_byte(u16 port, u8 data) 148 | { 149 | _asm 150 | { 151 | xor dx, dx 152 | mov al, data 153 | mov dx, port 154 | out dx, al 155 | }; 156 | } 157 | 158 | #else 159 | 160 | unsigned char 161 | in_byte(int index) 162 | { 163 | return IoRead8(index); 164 | } 165 | 166 | void 167 | out_byte(UINTN port, UINT8 data) 168 | { 169 | IoWrite8(port, data); 170 | } 171 | 172 | extern void cdecl set_int_flag(int); 173 | #endif 174 | 175 | u8 176 | read_cmos(u8 index) 177 | { 178 | u8 data; 179 | set_int_flag(0); 180 | out_byte(CMOS_INDX, index); 181 | data = in_byte(CMOS_DATA); 182 | set_int_flag(1); 183 | return data; 184 | } 185 | 186 | void write_cmos(u8 index, u8 data) 187 | { 188 | set_int_flag(0); 189 | out_byte(CMOS_INDX, index); 190 | out_byte(CMOS_DATA, data); 191 | set_int_flag(1); 192 | } 193 | 194 | int 195 | check_cmos_time_update(void) 196 | { 197 | u8 data; 198 | set_int_flag(0); 199 | out_byte(CMOS_INDX, RTC_STS_REG_A); 200 | data = (in_byte(CMOS_DATA) & BIT7); 201 | set_int_flag(1); 202 | return data; 203 | } 204 | 205 | void 206 | set_alarm_interrupt(int option) 207 | { 208 | u8 data; 209 | data = read_cmos(RTC_STS_REG_B); 210 | if (option){ 211 | //enable 212 | data |= BIT5; 213 | }else{ 214 | //clear 215 | data &= ~BIT5; 216 | } 217 | write_cmos(RTC_STS_REG_B, data); 218 | } 219 | 220 | void 221 | get_rtc_time(RTC_TIME *rtc_tm) 222 | { 223 | //hold if RTC update in progress. 224 | while(check_cmos_time_update()); 225 | rtc_tm->tm_sec = read_cmos(RTC_SECONDS); 226 | rtc_tm->tm_min = read_cmos(RTC_MINUTES); 227 | rtc_tm->tm_hour = read_cmos(RTC_HOURS); 228 | rtc_tm->tm_day_of_month = read_cmos(RTC_DAY_OF_MONTH); 229 | rtc_tm->tm_day_of_week = read_cmos(RTC_DAY_OF_WEEK); 230 | rtc_tm->tm_month = read_cmos(RTC_MONTH); 231 | rtc_tm->tm_year = read_cmos(RTC_YEAR); 232 | 233 | } 234 | 235 | void 236 | set_rtc_alarm(RTC_TIME *rtc_tm) 237 | { 238 | write_cmos(RTC_HOURS_ALARM, rtc_tm->tm_hour_alram); 239 | write_cmos(RTC_MINUTES_ALARM, rtc_tm->tm_min_alarm); 240 | write_cmos(RTC_SECONDS_ALARM, rtc_tm->tm_sec_alarm); 241 | } 242 | 243 | void 244 | calc_rtc_alarm(RTC_TIME *rtc_tm, u8 waketime) 245 | { 246 | u8 hrs, min, sec; 247 | unsigned long total_secs=0; 248 | 249 | hrs = BCD_TO_BIN(rtc_tm->tm_hour); 250 | min = BCD_TO_BIN(rtc_tm->tm_min); 251 | sec = BCD_TO_BIN(rtc_tm->tm_sec); 252 | 253 | //waketime only use second, change to total seconds for easy calculate 254 | total_secs = (unsigned long)hrs*3600 + min*60 + sec; 255 | total_secs += waketime; 256 | //printf("total_secs: %lu\n", total_secs); 257 | hrs = (u8)(total_secs / 3600); 258 | min = (u8)((total_secs % 3600) / 60); 259 | sec = (u8)((total_secs % 3600) % 60); 260 | //fixed: 24hrs issue 261 | if (hrs >= 24) 262 | hrs = 0; 263 | 264 | rtc_tm->tm_hour_alram = BIN_TO_BCD(hrs); 265 | rtc_tm->tm_min_alarm = BIN_TO_BCD(min); 266 | rtc_tm->tm_sec_alarm = BIN_TO_BCD(sec); 267 | 268 | } 269 | 270 | void 271 | clear_rtc_sts() 272 | { 273 | u8 data; 274 | data = in_byte(PMBASE+1); 275 | data &= ~BIT2; 276 | out_byte(PMBASE+1, data); 277 | } 278 | 279 | void 280 | set_rtc_event_enable(int option) 281 | { 282 | u8 data; 283 | data = in_byte(PMBASE+3); 284 | if (option){ 285 | data |= BIT2; 286 | }else{ 287 | data &= ~BIT2; 288 | } 289 | out_byte(PMBASE+3, data); 290 | } 291 | 292 | void 293 | set_slp_typ(u8 slp_typ) 294 | { 295 | out_byte(PMBASE+5, slp_typ|SLP_EN); 296 | sleep(10); 297 | } 298 | 299 | void 300 | sys_reboot() 301 | { 302 | out_byte(0xcf9, 0x6); 303 | sleep(10); 304 | } 305 | 306 | int 307 | print_usage(char *prog_name, FILE *channel, int ret_val) 308 | { 309 | fprintf(channel, "\nusage: %s [-s[-r] | -t xxx | -w xxx]\n", prog_name); 310 | fprintf(channel, "Options\n"); 311 | fprintf(channel, "-s shutdown\n"); 312 | fprintf(channel, "-r reboot\n"); 313 | fprintf(channel, "-t xxx timeout xxx seconds\n"); 314 | fprintf(channel, "-w xxx wakeup after xxx seconds\n"); 315 | return ret_val; 316 | } 317 | 318 | int 319 | main( 320 | int argc, 321 | char * argv[] 322 | ) 323 | { 324 | 325 | RTC_DEVICE *rtc_dev; 326 | int option, timeout, waketime; 327 | ACTION action = {0}; 328 | int i; 329 | char *c = NULL; 330 | 331 | option=timeout=waketime=0; 332 | 333 | rtc_dev = malloc(sizeof(RTC_DEVICE)); 334 | rtc_dev->get_time = get_rtc_time; 335 | rtc_dev->set_alarm = set_rtc_alarm; 336 | rtc_dev->calc_alarm = calc_rtc_alarm; 337 | 338 | while ((option = getopt (argc, argv, ":hsrt:w:")) !=-1) 339 | { 340 | switch(option) 341 | { 342 | default: 343 | // fprintf(stderr, "internal error: unknown case %c\n", optopt); 344 | return EXIT_FAILURE; 345 | #ifdef DOS 346 | case '?': 347 | fprintf(stderr, "error: unknown option: -%c\n", optopt); 348 | action.error = 1; 349 | break; 350 | case ':': 351 | fprintf(stderr, "error: missing argument for option -%c\n", optopt); 352 | action.error = 1; 353 | break; 354 | #endif 355 | case 'h': 356 | action.help = 1; 357 | break; 358 | case 's': 359 | action.shutdown = 1; 360 | break; 361 | case 'r': 362 | action.reboot = 1; 363 | break; 364 | case 't': 365 | sscanf(optarg, "%d", &timeout); 366 | break; 367 | case 'w': 368 | action.wakeup = 1; 369 | sscanf(optarg, "%d", &waketime); 370 | break; 371 | } 372 | } 373 | 374 | if (action.error || optind < argc) 375 | return print_usage(basename(argv[0]), stderr, EXIT_FAILURE); 376 | 377 | if (action.help) 378 | return print_usage(basename(argv[0]), stderr, EXIT_SUCCESS); 379 | 380 | //count number? 381 | if (timeout){ 382 | if (action.shutdown) 383 | c="shutdown"; 384 | if (action.reboot) 385 | c="reboot"; 386 | 387 | for(i=timeout; i>=1; i--){ 388 | fprintf(stderr, "time to %s %d \r", c, i); 389 | sleep(1); 390 | } 391 | } 392 | 393 | 394 | if (action.wakeup){ 395 | 396 | if (waketime == 0){ 397 | fprintf(stderr, "error: wake time zero!\n"); 398 | return EXIT_FAILURE; 399 | } 400 | //clear RTC status 401 | set_alarm_interrupt(0); 402 | set_rtc_event_enable(0); 403 | clear_rtc_sts(); 404 | 405 | rtc_dev->get_time(&rtc_dev->rtc_time); 406 | rtc_dev->calc_alarm(&rtc_dev->rtc_time, (u8)waketime); 407 | rtc_dev->set_alarm(&rtc_dev->rtc_time); 408 | 409 | set_alarm_interrupt(1); 410 | set_rtc_event_enable(1); 411 | 412 | printf("time: %d:%d:%d\n", BCD_TO_BIN(rtc_dev->rtc_time.tm_hour), \ 413 | BCD_TO_BIN(rtc_dev->rtc_time.tm_min), BCD_TO_BIN(rtc_dev->rtc_time.tm_sec)); 414 | printf("time alarm: %d:%d:%d\n", BCD_TO_BIN(rtc_dev->rtc_time.tm_hour_alram), \ 415 | BCD_TO_BIN(rtc_dev->rtc_time.tm_min_alarm), BCD_TO_BIN(rtc_dev->rtc_time.tm_sec_alarm)); 416 | } 417 | free(rtc_dev); 418 | 419 | if (action.shutdown){ 420 | //shutdown 421 | set_slp_typ(S5); 422 | } 423 | 424 | if (action.reboot){ 425 | sys_reboot(); 426 | } 427 | 428 | return 0; 429 | } 430 | -------------------------------------------------------------------------------- /Application/pwcycle/pwcycle.inf: -------------------------------------------------------------------------------- 1 | [Defines] 2 | INF_VERSION = 0x00010006 3 | BASE_NAME = pwcycle 4 | FILE_GUID = E1CF340C-51F0-411b-9CD4-64A366C9084D 5 | MODULE_TYPE = UEFI_APPLICATION 6 | VERSION_STRING = 0.1 7 | ENTRY_POINT = ShellCEntryLib 8 | 9 | # 10 | # VALID_ARCHITECTURES = IA32 X64 IPF 11 | # 12 | 13 | [Sources] 14 | pwcycle.c 15 | wiolib.asm 16 | 17 | [Packages] 18 | StdLib/StdLib.dec 19 | ShellPkg/ShellPkg.dec 20 | MdePkg/MdePkg.dec 21 | MyPkg/MyPkg.dec 22 | 23 | [LibraryClasses] 24 | LibC 25 | LibStdio 26 | IoLib 27 | 28 | [Guids] 29 | 30 | [Protocols] 31 | 32 | [BuildOptions] 33 | # MSFT:*_*_*_CC_FLAGS = /Od /D_UEFI_ /DCURL_STATICLIB 34 | -------------------------------------------------------------------------------- /Application/pwcycle/wiolib.asm: -------------------------------------------------------------------------------- 1 | 2 | ;.MODEL small 3 | ;.386 4 | 5 | PUBLIC set_int_flag 6 | .code 7 | 8 | set_int_flag proc 9 | push rbp 10 | mov rbp, rsp 11 | mov rax, [rbp+4] ;parameter 1 12 | cli 13 | cmp rax, 0 14 | jz ccc 15 | sti 16 | ccc: 17 | 18 | pop rbp 19 | 20 | ret 21 | set_int_flag endp 22 | 23 | END -------------------------------------------------------------------------------- /CSTAPP.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Construct UEFI Application Script 4 | # 5 | 6 | #check input 7 | if [ -z "$1" ]; then 8 | echo please give a file name! 9 | return 10 | fi 11 | #init 12 | mCurrentYear=$(date +%Y) 13 | mGUID=$(uuidgen) 14 | mDIR="./Application/$1/" 15 | mFILE_INF=$1".inf" 16 | mFILE_SRC=$1".c" 17 | 18 | #create files 19 | if [ ! -d $mDIR ]; then 20 | mkdir $mDIR 21 | fi 22 | touch $mDIR$mFILE_INF $mDIR$mFILE_SRC 23 | 24 | #write inf file 25 | cat < $mDIR$mFILE_INF 26 | ## 27 | # UEFI Application 28 | # 29 | # A shell application 30 | # 31 | # Free As Freedom @ $mCurrentYear 32 | # 33 | # 34 | ## 35 | 36 | [Defines] 37 | INF_VERSION = 0x00010006 38 | BASE_NAME = ${1^^} 39 | FILE_GUID = ${mGUID^^} 40 | MODULE_TYPE = UEFI_APPLICATION 41 | VERSION_STRING = 1.0 42 | ENTRY_POINT = ShellCEntryLib 43 | 44 | [Sources] 45 | $mFILE_SRC 46 | 47 | [Packages] 48 | MdePkg/MdePkg.dec 49 | MdeModulePkg/MdeModulePkg.dec 50 | ShellPkg/ShellPkg.dec 51 | MyPkg/MyPkg.dec 52 | 53 | [LibraryClasses] 54 | UefiApplicationEntryPoint 55 | UefiLib 56 | ShellCEntryLib 57 | 58 | [Protocols] 59 | 60 | EOF 61 | 62 | #write source c 63 | cat < $mDIR$mFILE_SRC 64 | 65 | /*++ 66 | 67 | FreeAsFreedom @ $mCurrentYear Kurt Qiao 68 | 69 | Module Name: 70 | 71 | $mFILE_SRC 72 | 73 | Abstract: 74 | 75 | Revision History 76 | 77 | --*/ 78 | 79 | #include 80 | #include 81 | #include "Library/UefiBootServicesTableLib.h" 82 | 83 | EFI_STATUS 84 | EFIAPI 85 | ShellAppMain ( 86 | IN UINTN Argc, 87 | IN CHAR16 **Argv 88 | ) 89 | { 90 | 91 | EFI_STATUS Status; 92 | Status = EFI_SUCCESS; 93 | 94 | return Status; 95 | } 96 | EOF 97 | -------------------------------------------------------------------------------- /Include/Library/AppCommon.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | #define ATA_PASS_THRU_SECOND_UNIT (1000 * 1000 * 10) // Timeout for one second. 6 | #define ATA_PASS_THRU_TIMEOUT (ATA_PASS_THRU_SECOND_UNIT * 10) // Timeout definition. 7 | #define ATA_CMD_IDENTIFY 0xEC 8 | #define ATAPI_CMD_IDENTIFY 0xA1 9 | 10 | EFI_STATUS 11 | AppPrintBuffer( 12 | UINT16 *Buffer 13 | ); 14 | 15 | BOOLEAN 16 | EFIAPI 17 | AppProbePCIByClassCode( 18 | UINT8 mBassCode, 19 | UINT8 mSubClass, 20 | UINT8 *mInterface OPTIONAL, 21 | UINT64 *mPCI_ADDRESS 22 | ); 23 | 24 | EFI_STATUS 25 | AppAhciIdentify( 26 | EFI_ATA_PASS_THRU_PROTOCOL *ATApt, 27 | UINT16 Port, 28 | UINT16 PortMultiplier, 29 | UINT8 *Buffer512B 30 | ); -------------------------------------------------------------------------------- /Include/Library/AppFrameWork.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | #include 5 | 6 | typedef struct _EFI_APP_FRAMEWORK_TABLE EFI_APP_FRAMEWORK_TABLE; 7 | 8 | typedef struct{ 9 | UINTN APP_OPERATIONS_NONE : 1; 10 | UINTN APP_OPERATIONS_PRINT_TEXT : 1; 11 | UINTN APP_OPERATIONS_PRINT_MENU : 1; 12 | UINTN APP_OPERATIONS_PRINT_HELP : 1; 13 | }APP_OPERATIONS; 14 | 15 | typedef 16 | EFI_STATUS 17 | (*APP_FRAMWORK_INI) ( 18 | UINTN Argc, 19 | CHAR16 **Argv 20 | ); 21 | 22 | typedef 23 | EFI_STATUS 24 | (*APP_FRAMWORK_HELP) ( 25 | ); 26 | 27 | struct _EFI_APP_FRAMEWORK_TABLE{ 28 | APP_FRAMWORK_INI Init; 29 | APP_FRAMWORK_HELP AppPrintHelp; 30 | APP_OPERATIONS Operations; 31 | VOID *PROTOCOL1; 32 | VOID *PROTOCOL2; 33 | VOID (*OP1)(VOID *Para1); 34 | }; 35 | 36 | 37 | EFI_STATUS 38 | EFIAPI 39 | ParseCommandLine( 40 | IN UINTN Argc, 41 | IN CHAR16 **Argv, 42 | EFI_APP_FRAMEWORK_TABLE *FtHandle 43 | ); 44 | 45 | -------------------------------------------------------------------------------- /Library/AppCommonLib/AppCommonLib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | 7 | 8 | EFI_STATUS 9 | AppPrintBuffer( 10 | UINT16 *Buffer 11 | ) 12 | { 13 | UINTN i; 14 | 15 | for (i = 0; i<=0xFF; i++){ 16 | if((i%10)==0){ 17 | if (i != 0); 18 | Print(L"\n"); 19 | Print(L"%.3d: ", i); 20 | } 21 | 22 | Print(L"%.4X ", Buffer[i]); 23 | } 24 | return EFI_SUCCESS; 25 | } 26 | 27 | /* 28 | Search a given PCI classcode and return it's PCI address 29 | */ 30 | BOOLEAN 31 | EFIAPI 32 | AppProbePCIByClassCode( 33 | UINT8 mBassCode, 34 | UINT8 mSubClass, 35 | UINT8 *mInterface OPTIONAL, 36 | UINT64 *mPCI_ADDRESS 37 | ) 38 | { 39 | EFI_STATUS Status; 40 | BOOLEAN Found; 41 | UINTN HandleCount; 42 | UINTN ThisBus; 43 | UINTN Bus, Dev, Func; 44 | UINTN Seg, Index; 45 | UINTN Count; 46 | 47 | PCI_DEVICE_INDEPENDENT_REGION *Hdr; 48 | PCI_TYPE_GENERIC PciHeader; 49 | EFI_PCI_IO_PROTOCOL *Pci; 50 | EFI_HANDLE *HandleBuffer; 51 | 52 | Found = FALSE; 53 | ZeroMem(mPCI_ADDRESS, sizeof(EFI_APP_FRAMEWORK_TABLE)*APP_MAX_CONTROLLER); 54 | //init 55 | Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPciIoProtocolGuid, \ 56 | NULL, &HandleCount, &HandleBuffer); 57 | if (EFI_ERROR(Status)){ 58 | Print(L"No PCI devices found!!\n"); 59 | return FALSE; 60 | } 61 | Count = 0; 62 | 63 | for (ThisBus = 0; ThisBus <= PCI_MAX_BUS; ThisBus++){ 64 | for (Index = 0; Index < HandleCount; Index++){ 65 | Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci); 66 | if(!EFI_ERROR(Status)){ 67 | Pci->GetLocation(Pci, &Seg, &Bus, &Dev, &Func); 68 | if (ThisBus != Bus) 69 | continue; 70 | Status = Pci->Pci.Read(Pci, EfiPciWidthUint32, 0, sizeof(PciHeader)/sizeof(UINT32), &PciHeader); 71 | if (!EFI_ERROR(Status)){ 72 | Hdr = &PciHeader.Bridge.Hdr; 73 | 74 | if ((Hdr->ClassCode[2] == mBassCode) && (Hdr->ClassCode[1] == mSubClass)){ 75 | 76 | if (mInterface != NULL){ 77 | if (Hdr->ClassCode[0] == *mInterface){ 78 | mPCI_ADDRESS[Count++] = PCI_LIB_ADDRESS(Bus, Dev, Func, 0); 79 | Found = TRUE; 80 | } 81 | }else{ 82 | mPCI_ADDRESS[Count++] = PCI_LIB_ADDRESS(Bus, Dev, Func, 0); 83 | Found = TRUE; 84 | 85 | } 86 | } //endif ((Hdr->ClassCode[2] == mBassCode) 87 | 88 | } //endif (!EFI_ERROR(Status)) 89 | } //endif (!EFI_ERROR(Status)) 1st 90 | }//for HandleCount 91 | }//for ThisBus 92 | 93 | return Found; 94 | } 95 | 96 | 97 | EFI_STATUS 98 | AppAhciIdentify( 99 | EFI_ATA_PASS_THRU_PROTOCOL *ATApt, 100 | UINT16 Port, 101 | UINT16 PortMultiplier, 102 | UINT8 *Buffer512B 103 | ) 104 | { 105 | EFI_STATUS Status; 106 | EFI_ATA_PASS_THRU_COMMAND_PACKET Packet; 107 | 108 | 109 | EFI_ATA_STATUS_BLOCK Asb; 110 | EFI_ATA_COMMAND_BLOCK Acb; 111 | 112 | 113 | Status = EFI_SUCCESS; 114 | ZeroMem(Buffer512B, sizeof(512*sizeof(UINT8))); 115 | // 116 | // Initialize Packet buffer. 117 | // 118 | ZeroMem ((char *)&Packet, sizeof(Packet)); 119 | ZeroMem ((char *)&Acb, sizeof(Acb)); 120 | ZeroMem ((char *)&Asb, sizeof(Asb)); 121 | Packet.Asb = &Asb; 122 | Packet.Acb = &Acb; 123 | 124 | Packet.InDataBuffer = Buffer512B; 125 | Packet.InTransferLength = 512; 126 | Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN; 127 | Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES; 128 | Packet.Timeout = ATA_PASS_THRU_TIMEOUT; 129 | Acb.AtaCommand = ATA_CMD_IDENTIFY; 130 | 131 | Status = ATApt->PassThru(ATApt, Port, PortMultiplier, &Packet, NULL); 132 | if (EFI_ERROR(Status)){ 133 | Acb.AtaCommand = ATAPI_CMD_IDENTIFY; //for ATAPI Indentify(ODD) 134 | Status = ATApt->PassThru(ATApt, Port, PortMultiplier, &Packet, NULL); 135 | } 136 | 137 | return Status; 138 | } 139 | -------------------------------------------------------------------------------- /Library/AppCommonLib/AppCommonLib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "Library/UefiBootServicesTableLib.h" 10 | #include 11 | #include 12 | #include 13 | 14 | #define APP_MAX_CONTROLLER 5 15 | 16 | -------------------------------------------------------------------------------- /Library/AppCommonLib/AppCommonLib.inf: -------------------------------------------------------------------------------- 1 | 2 | [Defines] 3 | INF_VERSION = 0x00010006 4 | BASE_NAME = AppCommonLib 5 | FILE_GUID = 95BF7161-F04F-4228-BF53-4D3E483CA473 6 | MODULE_TYPE = BASE 7 | VERSION_STRING = 0.1 8 | LIBRARY_CLASS = AppCommonLib 9 | 10 | [Sources] 11 | AppCommonLib.c 12 | 13 | [Packages] 14 | MdePkg/MdePkg.dec 15 | MdeModulePkg/MdeModulePkg.dec 16 | MyPkg/MyPkg.dec 17 | 18 | [LibraryClasses] 19 | UefiBootServicesTableLib 20 | UefiRuntimeServicesTableLib 21 | IoLib 22 | PciLib 23 | 24 | [Protocols] 25 | gEfiPciIoProtocolGuid -------------------------------------------------------------------------------- /Library/AppFrameWorkLib/AppFrameWorkLib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /*++ 5 | Routine Description: 6 | Parse the command line. 7 | 8 | Returns: 9 | EFI_SUCCESS - Successfully. 10 | OTHERS - Something failed. 11 | --*/ 12 | EFI_STATUS 13 | EFIAPI 14 | ParseCommandLine( 15 | IN UINTN Argc, 16 | IN CHAR16 **Argv, 17 | EFI_APP_FRAMEWORK_TABLE *FtHandle 18 | ) 19 | { 20 | EFI_STATUS Status; 21 | UINTN Index; 22 | 23 | Status = EFI_SUCCESS; 24 | if (Argc < 2) { 25 | FtHandle->Operations.APP_OPERATIONS_PRINT_TEXT = 1; 26 | return Status; 27 | } 28 | // 29 | // Check all parameters 30 | // 31 | for (Index = 1; Index < Argc; Index ++) { 32 | if ((Argv[Index][0] != L'-') || (Argv[Index][2] != L'\0')) { 33 | return EFI_INVALID_PARAMETER; 34 | } 35 | 36 | 37 | switch (Argv[Index][1]) { 38 | 39 | case L'g': 40 | case L'G': 41 | // 42 | // Run in graphic menu mode 43 | FtHandle->Operations.APP_OPERATIONS_PRINT_MENU = 1; 44 | break; 45 | 46 | case L'h': 47 | case L'H': 48 | case L'?': 49 | FtHandle->Operations.APP_OPERATIONS_PRINT_HELP = 1; 50 | break; 51 | 52 | default: 53 | Status = EFI_INVALID_PARAMETER; 54 | } 55 | } 56 | 57 | // 58 | // Done 59 | // 60 | return Status; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /Library/AppFrameWorkLib/AppFrameWorkLib.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include -------------------------------------------------------------------------------- /Library/AppFrameWorkLib/AppFrameWorkLib.inf: -------------------------------------------------------------------------------- 1 | 2 | [Defines] 3 | INF_VERSION = 0x00010006 4 | BASE_NAME = AppFrameWorkLib 5 | FILE_GUID = EA26C283-5FA5-4f98-95E0-AF64B318718C 6 | MODULE_TYPE = BASE 7 | VERSION_STRING = 0.1 8 | LIBRARY_CLASS = AppFrameWorkLib 9 | 10 | [Sources] 11 | AppFrameWorkLib.c 12 | AppFrameWorkLib.h 13 | 14 | [Packages] 15 | MdePkg/MdePkg.dec 16 | MdeModulePkg/MdeModulePkg.dec 17 | MyPkg/MyPkg.dec 18 | 19 | [LibraryClasses] 20 | UefiBootServicesTableLib 21 | UefiRuntimeServicesTableLib 22 | 23 | [Protocols] -------------------------------------------------------------------------------- /MyPkg.dec: -------------------------------------------------------------------------------- 1 | 2 | [Defines] 3 | DEC_SPECIFICATION = 0x00010006 4 | PACKAGE_NAME = MyPkg 5 | PACKAGE_GUID = 518D7206-48D3-4884-A821-4277BE766D53 6 | PACKAGE_VERSION = 0.1 7 | 8 | [Includes] 9 | Include 10 | ../StdLib/Include 11 | ../StdLib/Include/X64 12 | [LibraryClasses] 13 | AppFrameWorkLib|Include/Library/AppFrameWork.h 14 | AppCommonLib|Include/Library/AppCommon.h 15 | 16 | [Guids] 17 | 18 | [Ppis] 19 | 20 | [Protocols] -------------------------------------------------------------------------------- /MyPkg.dsc: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Defines] 4 | PLATFORM_NAME = MyPkg 5 | PLATFORM_GUID = 549867eb-059f-44d1-b1e1-13ec2f96c7a9 6 | PLATFORM_VERSION = 0.01 7 | DSC_SPECIFICATION = 0x00010006 8 | OUTPUT_DIRECTORY = Build/MyPkg 9 | SUPPORTED_ARCHITECTURES = IA32|IPF|X64 10 | BUILD_TARGETS = DEBUG|RELEASE 11 | SKUID_IDENTIFIER = DEFAULT 12 | 13 | [PcdsFeatureFlag] 14 | 15 | [PcdsFixedAtBuild] 16 | 17 | [PcdsFixedAtBuild.IPF] 18 | 19 | [LibraryClasses] 20 | # 21 | # Entry Point Libraries 22 | # 23 | UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf 24 | ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf 25 | #kurt2013.03.05 add for UEFI driver, err:"Instance of library class [UefiDriverEntryPoint] is not found" 26 | UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf 27 | DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf 28 | # 29 | # Common Libraries 30 | # 31 | BaseLib|MdePkg/Library/BaseLib/BaseLib.inf 32 | BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf 33 | UefiLib|MdePkg/Library/UefiLib/UefiLib.inf 34 | PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf 35 | PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf 36 | MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf 37 | UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf 38 | UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf 39 | DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf 40 | DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf 41 | PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf 42 | IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf 43 | SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf 44 | UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf 45 | HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf 46 | UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf 47 | PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf 48 | HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf 49 | ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf 50 | # FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf 51 | # SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf 52 | #kurt add+++ 53 | #for stdlib build fail 54 | # PathLib|ShellPkg/Library/BasePathLib/BasePathLib.inf 55 | # 56 | PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf 57 | PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf 58 | # 59 | # MyPkgLib 60 | # 61 | AppFrameWorkLib|MyPkg/Library/AppFrameWorkLib/AppFrameWorkLib.inf 62 | AppCommonLib|MyPkg/Library/AppCommonLib/AppCommonLib.inf 63 | #kurt add+++ 64 | [LibraryClasses.IA32] 65 | TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf 66 | # To run in an emulation environment, such as Nt32Pkg, comment out the TimerLib 67 | # description above and un-comment the line below. 68 | # TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf 69 | 70 | [LibraryClasses.X64] 71 | TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf 72 | 73 | [LibraryClasses.IPF] 74 | PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf 75 | TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf 76 | 77 | ################################################################################################### 78 | # 79 | # Components Section - list of the modules and components that will be processed by compilation 80 | # tools and the EDK II tools to generate PE32/PE32+/Coff image files. 81 | # 82 | # Note: The EDK II DSC file is not used to specify how compiled binary images get placed 83 | # into firmware volume images. This section is just a list of modules to compile from 84 | # source into UEFI-compliant binaries. 85 | # It is the FDF file that contains information on combining binary files into firmware 86 | # volume images, whose concept is beyond UEFI and is described in PI specification. 87 | # Binary modules do not need to be listed in this section, as they should be 88 | # specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi), 89 | # Logo (Logo.bmp), and etc. 90 | # There may also be modules listed in this section that are not required in the FDF file, 91 | # When a module listed here is excluded from FDF file, then UEFI-compliant binary will be 92 | # generated for it, but the binary will not be put into any firmware volume. 93 | # 94 | ################################################################################################### 95 | 96 | [Components] 97 | #### Sample Applications. 98 | MyPkg/Application/HddId/HddId.inf 99 | MyPkg/Application/AHCI/AHCI.inf 100 | MyPkg/Application/ctest/ctest.inf 101 | MyPkg/Application/HiiMenu/HiiMenu.inf 102 | MyPkg/Application/bootmgr/bootmgr.inf 103 | MyPkg/Application/GPT/GPT.inf 104 | MyPkg/Application/2048/2048.inf 105 | MyPkg/Application/mixbuild/mixtest.inf 106 | MyPkg/Application/pwcycle/pwcycle.inf 107 | 108 | ################################################################ 109 | # 110 | # See the additional comments below if you plan to run applications under the 111 | # Nt32 emulation environment. 112 | # 113 | [BuildOptions] 114 | INTEL:*_*_*_CC_FLAGS = /Qfreestanding 115 | MSFT:*_*_*_CC_FLAGS = /X /Zc:wchar_t 116 | GCC:*_*_*_CC_FLAGS = -ffreestanding -nostdinc -nostdlib 117 | 118 | ############################################################################## 119 | # 120 | # Include Boilerplate text required for building with the Standard Libraries. 121 | # 122 | ############################################################################## 123 | !include StdLib/StdLib.inc 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MyPkg 2 | ============ 3 | A sample UEFI Application package 4 | 5 | License: 6 | ------ 7 | Free as in Freedom(GPLv3). 8 | 9 | Build(windows): 10 | ------ 11 | 1. open VS cmd prompt 12 | 2. edksetup.bat 13 | 3. Build -a IA32/X64 -p MyPkg\MyPkg.dsc 14 | 4. output in Build\MyPkg 15 | 16 | > * check uefi.blogspot.com for how to setting VS UEFI build env 17 | > * refer to UEFI readme check how to build in linux 18 | 19 | Application: 20 | ------ 21 | 1. AHCI 22 | sample how to manipulate AHCI mmio issue HDD identify cmd and ODD eject cmd. 23 | 2. ctest 24 | a uefi sample import c language. 25 | 3. HddId: 26 | sample how to identify HDD data,support both AHCI and IDE mode. 27 | 4. HiiMenu 28 | sample how to use uefi HII. 29 | 5. bootmgr 30 | sample to manipulate UEFI variables, show/set BootOrder, show Boot####, BootCurrent. 31 | 6. GPT 32 | sample to read disk LBA1 to check GPT signature. 33 | 7. 2048 34 | small game in UEFI shell 35 | 8. pwcyle 36 | utility that shutdown and RTC wakeup, support both DOS version 37 | and UEFI version, by different build. --------------------------------------------------------------------------------