1 /* INCLUDES ******************************************************************/
6 #include "bootvid/bootvid.h"
8 /* GLOBALS *******************************************************************/
10 KSPIN_LOCK BootDriverLock
;
12 INBV_DISPLAY_STATE InbvDisplayState
;
13 BOOLEAN InbvBootDriverInstalled
;
14 BOOLEAN InbvDisplayDebugStrings
;
15 INBV_DISPLAY_STRING_FILTER InbvDisplayFilter
;
16 ULONG ProgressBarLeft
, ProgressBarTop
;
17 BOOLEAN ShowProgressBar
;
18 INBV_PROGRESS_STATE InbvProgressState
;
19 INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters
;
21 PUCHAR ResourceList
[64];
22 BOOLEAN SysThreadCreated
;
23 ROT_BAR_TYPE RotBarSelection
;
24 ULONG PltRotBarStatus
;
25 BT_PROGRESS_INDICATOR InbvProgressIndicator
= {0, 25, 0};
27 /* FUNCTIONS *****************************************************************/
31 FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
34 UNICODE_STRING UpString
= RTL_CONSTANT_STRING(L
"ntoskrnl.exe");
35 UNICODE_STRING MpString
= RTL_CONSTANT_STRING(L
"ntkrnlmp.exe");
36 PLIST_ENTRY NextEntry
, ListHead
;
37 PLDR_DATA_TABLE_ENTRY LdrEntry
;
38 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
;
39 LDR_RESOURCE_INFO ResourceInfo
;
43 /* Loop the driver list */
44 ListHead
= &LoaderBlock
->LoadOrderListHead
;
45 NextEntry
= ListHead
->Flink
;
46 while (NextEntry
!= ListHead
)
49 LdrEntry
= CONTAINING_RECORD(NextEntry
,
53 /* Check for a match */
54 if ((RtlEqualUnicodeString(&LdrEntry
->BaseDllName
, &UpString
, TRUE
)) ||
55 (RtlEqualUnicodeString(&LdrEntry
->BaseDllName
, &MpString
, TRUE
)))
62 /* Check if we found it */
63 if (NextEntry
!= ListHead
)
65 /* Try to find the resource */
66 ResourceInfo
.Type
= 2; //RT_BITMAP;
67 ResourceInfo
.Name
= ResourceId
;
68 ResourceInfo
.Language
= 0;
69 Status
= LdrFindResource_U(LdrEntry
->DllBase
,
73 if (NT_SUCCESS(Status
))
75 /* Access the resource */
77 Status
= LdrAccessResource(LdrEntry
->DllBase
,
81 if ((Data
) && (ResourceId
< 3))
83 KiBugCheckData
[4] ^= RtlComputeCrc32(0, Data
, Size
);
85 if (!NT_SUCCESS(Status
)) Data
= NULL
;
89 /* Return the pointer */
95 InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
99 BOOLEAN CustomLogo
= FALSE
;
102 /* Quit if we're already installed */
103 if (InbvBootDriverInstalled
) return TRUE
;
105 /* Initialize the lock and check the current display state */
106 KeInitializeSpinLock(&BootDriverLock
);
107 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
109 /* Check if we have a custom boot logo */
110 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
111 CustomLogo
= strstr(CommandLine
, "BOOTLOGO") ? TRUE
: FALSE
;
114 /* Initialize the video */
115 InbvBootDriverInstalled
= VidInitialize(FALSE
);
116 if (InbvBootDriverInstalled
)
118 /* Now reset the display, but only if there's a custom boot logo */
119 VidResetDisplay(CustomLogo
);
121 /* Find bitmap resources in the kernel */
122 ResourceCount
= min(IDB_CLUSTER_SERVER
, Count
);
123 for (i
= 1; i
<= Count
; i
++)
126 ResourceList
[i
] = FindBitmapResource(LoaderBlock
, i
);
129 /* Set the progress bar ranges */
130 InbvSetProgressBarSubset(0, 100);
133 /* Return install state */
134 return InbvBootDriverInstalled
;
139 InbvAcquireLock(VOID
)
143 /* Check if we're at dispatch level or lower */
144 OldIrql
= KeGetCurrentIrql();
145 if (OldIrql
<= DISPATCH_LEVEL
)
147 /* Loop until the lock is free */
148 while (!KeTestSpinLock(&BootDriverLock
));
150 /* Raise IRQL to dispatch level */
151 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
154 /* Acquire the lock */
155 KiAcquireSpinLock(&BootDriverLock
);
156 InbvOldIrql
= OldIrql
;
161 InbvReleaseLock(VOID
)
165 /* Capture the old IRQL */
166 OldIrql
= InbvOldIrql
;
168 /* Release the driver lock */
169 KiReleaseSpinLock(&BootDriverLock
);
171 /* If we were at dispatch level or lower, restore the old IRQL */
172 if (InbvOldIrql
<= DISPATCH_LEVEL
) KeLowerIrql(OldIrql
);
177 InbvEnableBootDriver(IN BOOLEAN Enable
)
179 /* Check if we're installed */
180 if (InbvBootDriverInstalled
)
182 /* Check for lost state */
183 if (InbvDisplayState
>= INBV_DISPLAY_STATE_LOST
) return;
185 /* Acquire the lock */
188 /* Cleanup the screen if we own it */
189 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
) VidCleanUp();
191 /* Set the new display state */
192 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
193 INBV_DISPLAY_STATE_DISABLED
;
195 /* Release the lock */
200 /* Set the new display state */
201 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
202 INBV_DISPLAY_STATE_DISABLED
;
208 InbvAcquireDisplayOwnership(VOID
)
210 /* Check if we have a callback and we're just acquiring it now */
211 if ((InbvResetDisplayParameters
) &&
212 (InbvDisplayState
== INBV_DISPLAY_STATE_LOST
))
214 /* Call the callback */
215 InbvResetDisplayParameters(80, 50);
218 /* Acquire the display */
219 InbvDisplayState
= INBV_DISPLAY_STATE_OWNED
;
224 InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned
)
226 /* Set the new display state */
227 InbvDisplayState
= DisplayOwned
? INBV_DISPLAY_STATE_OWNED
:
228 INBV_DISPLAY_STATE_LOST
;
233 InbvCheckDisplayOwnership(VOID
)
235 /* Return if we own it or not */
236 return InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
;
241 InbvGetDisplayState(VOID
)
243 /* Return the actual state */
244 return InbvDisplayState
;
249 InbvDisplayString(IN PCHAR String
)
251 /* Make sure we own the display */
252 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
254 /* If we're not allowed, return success anyway */
255 if (!InbvDisplayDebugStrings
) return TRUE
;
257 /* Check if a filter is installed */
258 if (InbvDisplayFilter
) InbvDisplayFilter(&String
);
260 /* Acquire the lock */
263 /* Make sure we're installed and display the string */
264 if (InbvBootDriverInstalled
) VidDisplayString((PUCHAR
) String
);
266 /* Print the string on the EMS port */
268 HeadlessCmdPutString
,
270 strlen(String
) + sizeof(ANSI_NULL
),
274 /* Release the lock */
281 /* We don't own it, fail */
287 InbvEnableDisplayString(IN BOOLEAN Enable
)
291 /* Get the old setting */
292 OldSetting
= InbvDisplayDebugStrings
;
295 InbvDisplayDebugStrings
= Enable
;
297 /* Return the old setting */
303 InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter
)
305 /* Save the filter */
306 InbvDisplayFilter
= Filter
;
311 InbvIsBootDriverInstalled(VOID
)
313 /* Return driver state */
314 return InbvBootDriverInstalled
;
319 InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback
)
321 /* Check if we're installed */
322 if (InbvBootDriverInstalled
)
324 /* Acquire the lock and cleanup if we own the screen */
326 if (InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
) VidCleanUp();
328 /* Set the reset callback and display state */
329 InbvResetDisplayParameters
= Callback
;
330 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
332 /* Release the lock */
337 /* Set the reset callback and display state */
338 InbvResetDisplayParameters
= Callback
;
339 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
345 InbvResetDisplay(VOID
)
347 /* Check if we're installed and we own it */
348 if ((InbvBootDriverInstalled
) &&
349 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
352 VidResetDisplay(TRUE
);
356 /* Nothing to reset */
362 InbvSetScrollRegion(IN ULONG Left
,
367 /* Just call bootvid */
368 VidSetScrollRegion(Left
, Top
, Width
, Height
);
373 InbvSetTextColor(IN ULONG Color
)
375 /* FIXME: Headless */
377 /* Update the text color */
378 VidSetTextColor(Color
);
383 InbvSolidColorFill(IN ULONG Left
,
389 /* Make sure we own it */
390 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
392 /* Acquire the lock */
395 /* Check if we're installed */
396 if (InbvBootDriverInstalled
)
399 VidSolidColorFill(Left
, Top
, Width
, Height
, (UCHAR
)Color
);
402 /* FIXME: Headless */
404 /* Release the lock */
411 InbvUpdateProgressBar(IN ULONG Progress
)
413 ULONG FillCount
, BoundedProgress
;
415 /* Make sure the progress bar is enabled, that we own and are installed */
416 if ((ShowProgressBar
) &&
417 (InbvBootDriverInstalled
) &&
418 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
420 /* Compute fill count */
421 BoundedProgress
= (InbvProgressState
.Floor
/ 100) + Progress
;
422 FillCount
= 121 * (InbvProgressState
.Bias
* BoundedProgress
) / 1000000;
424 /* Acquire the lock */
427 /* Fill the progress bar */
428 VidSolidColorFill(ProgressBarLeft
,
430 ProgressBarLeft
+ FillCount
,
434 /* Release the lock */
441 InbvBufferToScreenBlt(IN PUCHAR Buffer
,
448 /* Check if we're installed and we own it */
449 if ((InbvBootDriverInstalled
) &&
450 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
453 VidBufferToScreenBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
459 InbvBitBlt(IN PUCHAR Buffer
,
463 /* Check if we're installed and we own it */
464 if ((InbvBootDriverInstalled
) &&
465 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
467 /* Acquire the lock */
471 VidBitBlt(Buffer
, X
, Y
);
473 /* Release the lock */
480 InbvScreenToBufferBlt(IN PUCHAR Buffer
,
487 /* Check if we're installed and we own it */
488 if ((InbvBootDriverInstalled
) &&
489 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
492 VidScreenToBufferBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
498 InbvSetProgressBarCoordinates(IN ULONG Left
,
501 /* Update the coordinates */
502 ProgressBarLeft
= Left
;
503 ProgressBarTop
= Top
;
505 /* Enable the progress bar */
506 ShowProgressBar
= TRUE
;
511 InbvSetProgressBarSubset(IN ULONG Floor
,
515 ASSERT(Floor
< Ceiling
);
516 ASSERT(Ceiling
<= 100);
518 /* Update the progress bar state */
519 InbvProgressState
.Floor
= Floor
* 100;
520 InbvProgressState
.Ceiling
= Ceiling
* 100;
521 InbvProgressState
.Bias
= (Ceiling
* 100) - Floor
;
526 InbvIndicateProgress(VOID
)
530 /* Increase progress */
531 InbvProgressIndicator
.Count
++;
533 /* Compute new percentage */
534 Percentage
= min(100 * InbvProgressIndicator
.Count
/
535 InbvProgressIndicator
.Expected
,
537 if (Percentage
!= InbvProgressIndicator
.Percentage
)
539 /* Percentage has moved, update the progress bar */
540 InbvProgressIndicator
.Percentage
= Percentage
;
541 InbvUpdateProgressBar(Percentage
);
547 InbvGetResourceAddress(IN ULONG ResourceNumber
)
549 /* Validate the resource number */
550 if (ResourceNumber
> ResourceCount
) return NULL
;
552 /* Return the address */
553 return ResourceList
[ResourceNumber
--];
558 NtDisplayString(IN PUNICODE_STRING DisplayString
)
560 OEM_STRING OemString
;
562 /* Convert the string to OEM and display it */
563 RtlUnicodeStringToOemString(&OemString
, DisplayString
, TRUE
);
564 InbvDisplayString(OemString
.Buffer
);
565 RtlFreeOemString(&OemString
);
568 return STATUS_SUCCESS
;
573 DisplayBootBitmap(IN BOOLEAN SosMode
)
575 PVOID Header
, Band
, Text
, Screen
;
576 ROT_BAR_TYPE TempRotBarSelection
= RB_UNSPECIFIED
;
579 /* Check if the system thread has already been created */
580 if (SysThreadCreated
)
582 /* Reset the progress bar */
584 RotBarSelection
= RB_UNSPECIFIED
;
588 /* Check if this is SOS mode */
589 ShowProgressBar
= FALSE
;
592 /* Check if this is a server OS */
593 if (SharedUserData
->NtProductType
== NtProductWinNt
)
595 /* It's not, set workstation settings */
596 InbvSetTextColor(15);
597 InbvSolidColorFill(0, 0, 639, 479, 7);
598 InbvSolidColorFill(0, 421, 639, 479, 1);
601 Header
= InbvGetResourceAddress(IDB_LOGO_HEADER
);
602 Band
= InbvGetResourceAddress(IDB_LOGO_BAND
);
606 /* Set server settings */
607 InbvSetTextColor(14);
608 InbvSolidColorFill(0, 0, 639, 479, 6);
609 InbvSolidColorFill(0, 421, 639, 479, 1);
612 Header
= InbvGetResourceAddress(IDB_SERVER_HEADER
);
613 Band
= InbvGetResourceAddress(IDB_SERVER_BAND
);
616 /* Set the scrolling region */
617 InbvSetScrollRegion(32, 80, 631, 400);
619 /* Make sure we have resources */
620 if ((Header
) && (Band
))
622 /* BitBlt them on the screen */
623 InbvBitBlt(Band
, 0, 419);
624 InbvBitBlt(Header
, 0, 0);
629 /* Is the boot driver installed? */
631 if (!InbvBootDriverInstalled
) return;
633 /* Load the standard boot screen */
634 Screen
= InbvGetResourceAddress(IDB_BOOT_LOGO
);
635 if (SharedUserData
->NtProductType
== NtProductWinNt
)
637 /* Workstation product, display appropriate status bar color */
638 InbvGetResourceAddress(IDB_BAR_PRO
);
642 /* Display correct branding based on server suite */
643 if (ExVerifySuite(StorageServer
))
645 /* Storage Server Edition */
646 Text
= InbvGetResourceAddress(IDB_STORAGE_SERVER
);
648 else if (ExVerifySuite(ComputeServer
))
650 /* Compute Cluster Edition */
651 Text
= InbvGetResourceAddress(IDB_CLUSTER_SERVER
);
656 Text
= InbvGetResourceAddress(IDB_SERVER_LOGO
);
659 /* Server product, display appropriate status bar color */
660 InbvGetResourceAddress(IDB_BAR_SERVER
);
663 /* Make sure we had a logo */
666 /* Choose progress bar */
667 TempRotBarSelection
= RB_SQUARE_CELLS
;
669 /* Blit the background */
670 InbvBitBlt(Screen
, 0, 0);
672 /* Set progress bar coordinates and display it */
673 InbvSetProgressBarCoordinates(257, 352);
675 /* Check for non-workstation products */
676 if (SharedUserData
->NtProductType
!= NtProductWinNt
)
678 /* Overwrite part of the logo for a server product */
679 InbvScreenToBufferBlt(Buffer
, 413, 237, 7, 7, 8);
680 InbvSolidColorFill(418, 230, 454, 256, 0);
681 InbvBufferToScreenBlt(Buffer
, 413, 237, 7, 7, 8);
683 /* In setup mode, you haven't selected a SKU yet */
684 if (ExpInTextModeSetup
) Text
= NULL
;
688 /* Draw the SKU text if it exits */
689 if (Text
) InbvBitBlt(Text
, 180, 121);
691 /* Draw the progress bar bit */
692 // if (Bar) InbvBitBlt(Bar, 0, 0);
695 /* Do we have a system thread? */
696 if (SysThreadCreated
)
698 /* We do, set the progress bar location */
700 RotBarSelection
= TempRotBarSelection
;
708 FinalizeBootLogo(VOID
)
710 /* Acquire lock and check the display state */
712 if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED
)
714 /* Clear the screen */
715 VidSolidColorFill(0, 0, 639, 479, 0);
718 /* Reset progress bar and lock */