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
;
44 /* Loop the driver list */
45 ListHead
= &LoaderBlock
->LoadOrderListHead
;
46 NextEntry
= ListHead
->Flink
;
47 while (NextEntry
!= ListHead
)
50 LdrEntry
= CONTAINING_RECORD(NextEntry
,
54 /* Check for a match */
55 if ((RtlEqualUnicodeString(&LdrEntry
->BaseDllName
, &UpString
, TRUE
)) ||
56 (RtlEqualUnicodeString(&LdrEntry
->BaseDllName
, &MpString
, TRUE
)))
63 /* Check if we found it */
64 if (NextEntry
!= ListHead
)
66 /* Try to find the resource */
67 ResourceInfo
.Type
= 2;
68 ResourceInfo
.Name
= ResourceId
;
69 ResourceInfo
.Language
= 0;
70 Status
= LdrFindResource_U(LdrEntry
->DllBase
,
74 if (NT_SUCCESS(Status
))
76 /* Access the resource */
77 Status
= LdrAccessResource(LdrEntry
->DllBase
,
81 if (!NT_SUCCESS(Status
)) Data
= NULL
;
85 /* Return the pointer */
91 InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
95 BOOLEAN CustomLogo
= FALSE
;
98 /* Quit if we're already installed */
99 if (InbvBootDriverInstalled
) return TRUE
;
101 /* Initialize the lock and check the current display state */
102 KeInitializeSpinLock(&BootDriverLock
);
103 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
105 /* Check if we have a custom boot logo */
106 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
107 CustomLogo
= strstr(CommandLine
, "BOOTLOGO") ? TRUE
: FALSE
;
110 /* Initialize the video */
111 InbvBootDriverInstalled
= VidInitialize(FALSE
);
112 if (InbvBootDriverInstalled
)
114 /* Now reset the display, but only if there's a custom boot logo */
115 VidResetDisplay(CustomLogo
);
117 /* Find bitmap resources in the kernel */
118 ResourceCount
= Count
;
119 for (i
= 0; i
< Count
; i
++)
122 ResourceList
[i
] = FindBitmapResource(LoaderBlock
, i
);
125 /* Set the progress bar ranges */
126 InbvSetProgressBarSubset(0, 100);
129 /* Return install state */
130 return InbvBootDriverInstalled
;
135 InbvAcquireLock(VOID
)
137 /* Check if we're below dispatch level */
138 InbvOldIrql
= KeGetCurrentIrql();
139 if (InbvOldIrql
< DISPATCH_LEVEL
)
141 /* Raise IRQL to dispatch level */
142 KeRaiseIrql(DISPATCH_LEVEL
, &InbvOldIrql
);
145 /* Acquire the lock */
146 KiAcquireSpinLock(&BootDriverLock
);
151 InbvReleaseLock(VOID
)
153 /* Release the driver lock */
154 KiReleaseSpinLock(&BootDriverLock
);
156 /* If we were below dispatch level, lower IRQL back */
157 if (InbvOldIrql
< DISPATCH_LEVEL
) KeLowerIrql(InbvOldIrql
);
162 InbvEnableBootDriver(IN BOOLEAN Enable
)
164 /* Check if we're installed */
165 if (InbvBootDriverInstalled
)
167 /* Check for lost state */
168 if (InbvDisplayState
>= INBV_DISPLAY_STATE_LOST
) return;
170 /* Acquire the lock */
173 /* Cleanup the screen if we own it */
174 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
) VidCleanUp();
176 /* Set the new display state */
177 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
178 INBV_DISPLAY_STATE_DISABLED
;
180 /* Release the lock */
185 /* Set the new display state */
186 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
187 INBV_DISPLAY_STATE_DISABLED
;
193 InbvAcquireDisplayOwnership(VOID
)
195 /* Check if we have a callback and we're just acquiring it now */
196 if ((InbvResetDisplayParameters
) &&
197 (InbvDisplayState
== INBV_DISPLAY_STATE_LOST
))
199 /* Call the callback */
200 InbvResetDisplayParameters(80, 50);
203 /* Acquire the display */
204 InbvDisplayState
= INBV_DISPLAY_STATE_OWNED
;
209 InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned
)
211 /* Set the new display state */
212 InbvDisplayState
= DisplayOwned
? INBV_DISPLAY_STATE_OWNED
:
213 INBV_DISPLAY_STATE_LOST
;
218 InbvCheckDisplayOwnership(VOID
)
220 /* Return if we own it or not */
221 return InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
;
226 InbvGetDisplayState(VOID
)
228 /* Return the actual state */
229 return InbvDisplayState
;
234 InbvDisplayString(IN PCHAR String
)
236 /* Make sure we own the display */
237 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
239 /* If we're not allowed, return success anyway */
240 if (!InbvDisplayDebugStrings
) return TRUE
;
242 /* Check if a filter is installed */
243 if (InbvDisplayFilter
) InbvDisplayFilter(&String
);
245 /* Acquire the lock */
248 /* Make sure we're installed and display the string */
249 if (InbvBootDriverInstalled
) VidDisplayString((PUCHAR
) String
);
251 /* Call Headless (We don't support headless for now)
252 HeadlessDispatch(DISPLAY_STRING); */
254 /* Release the lock */
261 /* We don't own it, fail */
267 InbvEnableDisplayString(IN BOOLEAN Enable
)
271 /* Get the old setting */
272 OldSetting
= InbvDisplayDebugStrings
;
275 InbvDisplayDebugStrings
= Enable
;
277 /* Return the old setting */
283 InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter
)
285 /* Save the filter */
286 InbvDisplayFilter
= Filter
;
291 InbvIsBootDriverInstalled(VOID
)
293 /* Return driver state */
294 return InbvBootDriverInstalled
;
299 InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback
)
301 /* Check if we're installed */
302 if (InbvBootDriverInstalled
)
304 /* Acquire the lock and cleanup if we own the screen */
306 if (InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
) VidCleanUp();
308 /* Set the reset callback and display state */
309 InbvResetDisplayParameters
= Callback
;
310 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
312 /* Release the lock */
317 /* Set the reset callback and display state */
318 InbvResetDisplayParameters
= Callback
;
319 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
325 InbvResetDisplay(VOID
)
327 /* Check if we're installed and we own it */
328 if ((InbvBootDriverInstalled
) &&
329 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
332 VidResetDisplay(TRUE
);
336 /* Nothing to reset */
342 InbvSetScrollRegion(IN ULONG Left
,
347 /* Just call bootvid */
348 VidSetScrollRegion(Left
, Top
, Width
, Height
);
353 InbvSetTextColor(IN ULONG Color
)
355 /* FIXME: Headless */
357 /* Update the text color */
358 VidSetTextColor(Color
);
363 InbvSolidColorFill(IN ULONG Left
,
369 /* Make sure we own it */
370 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
372 /* Acquire the lock */
375 /* Check if we're installed */
376 if (InbvBootDriverInstalled
)
379 VidSolidColorFill(Left
, Top
, Width
, Height
, (UCHAR
)Color
);
382 /* FIXME: Headless */
384 /* Release the lock */
391 InbvUpdateProgressBar(IN ULONG Progress
)
393 ULONG FillCount
, BoundedProgress
;
395 /* Make sure the progress bar is enabled, that we own and are installed */
396 if ((ShowProgressBar
) &&
397 (InbvBootDriverInstalled
) &&
398 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
400 /* Compute fill count */
401 BoundedProgress
= (InbvProgressState
.Floor
/ 100) + Progress
;
402 FillCount
= 121 * (InbvProgressState
.Bias
* BoundedProgress
) / 1000000;
404 /* Acquire the lock */
407 /* Fill the progress bar */
408 VidSolidColorFill(ProgressBarLeft
,
410 ProgressBarLeft
+ FillCount
,
414 /* Release the lock */
421 InbvBufferToScreenBlt(IN PUCHAR Buffer
,
428 /* Check if we're installed and we own it */
429 if ((InbvBootDriverInstalled
) &&
430 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
433 VidBufferToScreenBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
439 InbvBitBlt(IN PUCHAR Buffer
,
443 /* Check if we're installed and we own it */
444 if ((InbvBootDriverInstalled
) &&
445 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
447 /* Acquire the lock */
451 VidBitBlt(Buffer
, X
, Y
);
453 /* Release the lock */
460 InbvScreenToBufferBlt(IN PUCHAR Buffer
,
467 /* Check if we're installed and we own it */
468 if ((InbvBootDriverInstalled
) &&
469 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
472 VidScreenToBufferBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
478 InbvSetProgressBarCoordinates(IN ULONG Left
,
481 /* Update the coordinates */
482 ProgressBarLeft
= Left
;
483 ProgressBarTop
= Top
;
485 /* Enable the progress bar */
486 ShowProgressBar
= TRUE
;
491 InbvSetProgressBarSubset(IN ULONG Floor
,
495 ASSERT(Floor
< Ceiling
);
496 ASSERT(Ceiling
<= 100);
498 /* Update the progress bar state */
499 InbvProgressState
.Floor
= Floor
* 100;
500 InbvProgressState
.Ceiling
= Ceiling
* 100;
501 InbvProgressState
.Bias
= (Ceiling
* 100) - Floor
;
506 InbvIndicateProgress(VOID
)
510 /* Increase progress */
511 InbvProgressIndicator
.Count
++;
513 /* Compute new percentage */
514 Percentage
= min(100 * InbvProgressIndicator
.Count
/
515 InbvProgressIndicator
.Expected
,
517 if (Percentage
!= InbvProgressIndicator
.Percentage
)
519 /* Percentage has moved, update the progress bar */
520 InbvProgressIndicator
.Percentage
= Percentage
;
521 InbvUpdateProgressBar(Percentage
);
527 InbvGetResourceAddress(IN ULONG ResourceNumber
)
529 /* Validate the resource number */
530 if (ResourceNumber
> ResourceCount
) return NULL
;
532 /* Return the address */
533 return ResourceList
[ResourceNumber
--];
538 NtDisplayString(IN PUNICODE_STRING DisplayString
)
540 OEM_STRING OemString
;
542 /* Convert the string to OEM and display it */
543 RtlUnicodeStringToOemString(&OemString
, DisplayString
, TRUE
);
544 InbvDisplayString(OemString
.Buffer
);
545 RtlFreeOemString(&OemString
);
548 return STATUS_SUCCESS
;
553 DisplayBootBitmap(IN BOOLEAN SosMode
)
555 PVOID Header
, Band
, Bar
, Text
, Screen
;
556 ROT_BAR_TYPE TempRotBarSelection
= RB_UNSPECIFIED
;
559 /* Check if the system thread has already been created */
560 if (SysThreadCreated
)
562 /* Reset the progress bar */
568 /* Check if this is SOS mode */
569 ShowProgressBar
= FALSE
;
572 /* Check if this is a server OS */
573 if (SharedUserData
->NtProductType
== NtProductWinNt
)
575 /* It's not, set workstation settings */
576 InbvSetTextColor(15);
577 InbvSolidColorFill(0, 0, 639, 479, 7);
578 InbvSolidColorFill(0, 421, 639, 479, 1);
581 Header
= InbvGetResourceAddress(IDB_LOGO_HEADER
);
582 Band
= InbvGetResourceAddress(IDB_LOGO_BAND
);
586 /* Set server settings */
587 InbvSetTextColor(14);
588 InbvSolidColorFill(0, 0, 639, 479, 6);
589 InbvSolidColorFill(0, 421, 639, 479, 1);
592 Header
= InbvGetResourceAddress(IDB_SERVER_HEADER
);
593 Band
= InbvGetResourceAddress(IDB_SERVER_BAND
);
596 /* Set the scrolling region */
597 InbvSetScrollRegion(32, 80, 631, 400);
599 /* Make sure we have resources */
600 if ((Header
) && (Band
))
602 /* BitBlt them on the screen */
603 InbvBitBlt(Band
, 0, 419);
604 InbvBitBlt(Header
, 0, 0);
609 /* Is the boot driver installed? */
611 if (!InbvBootDriverInstalled
) return;
613 /* Load the standard boot screen */
614 Screen
= InbvGetResourceAddress(IDB_BOOT_LOGO
);
615 if (SharedUserData
->NtProductType
== NtProductWinNt
)
617 /* Workstation product, display appropriate status bar color */
618 Bar
= InbvGetResourceAddress(IDB_BAR_PRO
);
622 /* Display correct branding based on server suite */
623 if (ExVerifySuite(StorageServer
))
625 /* Storage Server Edition */
626 Text
= InbvGetResourceAddress(IDB_STORAGE_SERVER
);
628 else if (ExVerifySuite(ComputeServer
))
630 /* Compute Cluster Edition */
631 Text
= InbvGetResourceAddress(IDB_CLUSTER_SERVER
);
636 Text
= InbvGetResourceAddress(IDB_SERVER_LOGO
);
639 /* Server product, display appropriate status bar color */
640 Bar
= InbvGetResourceAddress(IDB_BAR_SERVER
);
643 /* Make sure we had a logo */
646 /* Choose progress bar */
647 TempRotBarSelection
= RB_SQUARE_CELLS
;
649 /* Blit the background */
650 InbvBitBlt(Screen
, 0, 0);
652 /* Set progress bar coordinates and display it */
653 InbvSetProgressBarCoordinates(257, 352);
655 /* Check for non-workstation products */
656 if (SharedUserData
->NtProductType
!= NtProductWinNt
)
658 /* Overwrite part of the logo for a server product */
659 InbvScreenToBufferBlt(Buffer
, 413, 237, 7, 7, 8);
660 InbvSolidColorFill(418, 230, 454, 256, 0);
661 InbvBufferToScreenBlt(Buffer
, 413, 237, 7, 7, 8);
663 /* In setup mode, you haven't selected a SKU yet */
664 if (ExpInTextModeSetup
) Text
= NULL
;
668 /* Draw the SKU text if it exits */
669 if (Text
) InbvBitBlt(Text
, 180, 121);
671 /* Draw the progress bar bit */
672 // if (Bar) InbvBitBlt(Bar, 0, 0);
675 /* Do we have a system thread? */
676 if (SysThreadCreated
)
678 /* We do, set the progress bar location */
680 RotBarSelection
= TempRotBarSelection
;
688 FinalizeBootLogo(VOID
)
690 /* Acquire lock and check the display state */
692 if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED
)
694 /* Clear the screen */
695 VidSolidColorFill(0, 0, 639, 479, 0);
698 /* Reset progress bar and lock */