1 /* INCLUDES ******************************************************************/
6 #include "bootvid/bootvid.h"
8 /* GLOBALS *******************************************************************/
10 KSPIN_LOCK BootDriverLock
;
12 INBV_DISPLAY_STATE InbvDisplayState
;
13 BOOLEAN InbvBootDriverInstalled
= FALSE
;
14 BOOLEAN InbvDisplayDebugStrings
= FALSE
;
15 INBV_DISPLAY_STRING_FILTER InbvDisplayFilter
;
16 ULONG ProgressBarLeft
, ProgressBarTop
;
17 BOOLEAN ShowProgressBar
= FALSE
;
18 INBV_PROGRESS_STATE InbvProgressState
;
19 INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters
;
21 PUCHAR ResourceList
[64];
22 BOOLEAN SysThreadCreated
= FALSE
;
23 ROT_BAR_TYPE RotBarSelection
;
24 ULONG PltRotBarStatus
;
25 BT_PROGRESS_INDICATOR InbvProgressIndicator
= {0, 25, 0};
27 /* FUNCTIONS *****************************************************************/
32 FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
35 UNICODE_STRING UpString
= RTL_CONSTANT_STRING(L
"ntoskrnl.exe");
36 UNICODE_STRING MpString
= RTL_CONSTANT_STRING(L
"ntkrnlmp.exe");
37 PLIST_ENTRY NextEntry
, ListHead
;
38 PLDR_DATA_TABLE_ENTRY LdrEntry
;
39 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
;
40 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; //RT_BITMAP;
68 ResourceInfo
.Name
= ResourceId
;
69 ResourceInfo
.Language
= 0;
70 Status
= LdrFindResource_U(LdrEntry
->DllBase
,
74 if (NT_SUCCESS(Status
))
76 /* Access the resource */
78 Status
= LdrAccessResource(LdrEntry
->DllBase
,
82 if ((Data
) && (ResourceId
< 3))
84 KiBugCheckData
[4] ^= RtlComputeCrc32(0, Data
, Size
);
86 if (!NT_SUCCESS(Status
)) Data
= NULL
;
90 /* Return the pointer */
97 InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
101 BOOLEAN CustomLogo
= FALSE
;
104 /* Quit if we're already installed */
105 if (InbvBootDriverInstalled
) return TRUE
;
107 /* Initialize the lock and check the current display state */
108 KeInitializeSpinLock(&BootDriverLock
);
109 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
111 /* Check if we have a custom boot logo */
112 CommandLine
= _strupr(LoaderBlock
->LoadOptions
);
113 CustomLogo
= strstr(CommandLine
, "BOOTLOGO") ? TRUE
: FALSE
;
116 /* Initialize the video */
117 InbvBootDriverInstalled
= VidInitialize(FALSE
);
118 if (InbvBootDriverInstalled
)
120 /* Now reset the display, but only if there's a custom boot logo */
121 VidResetDisplay(CustomLogo
);
123 /* Find bitmap resources in the kernel */
124 ResourceCount
= min(IDB_CLUSTER_SERVER
, Count
);
125 for (i
= 1; i
<= Count
; i
++)
128 ResourceList
[i
] = FindBitmapResource(LoaderBlock
, i
);
131 /* Set the progress bar ranges */
132 InbvSetProgressBarSubset(0, 100);
135 /* Return install state */
136 return InbvBootDriverInstalled
;
141 InbvAcquireLock(VOID
)
145 /* Check if we're at dispatch level or lower */
146 OldIrql
= KeGetCurrentIrql();
147 if (OldIrql
<= DISPATCH_LEVEL
)
149 /* Loop until the lock is free */
150 while (!KeTestSpinLock(&BootDriverLock
));
152 /* Raise IRQL to dispatch level */
153 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
156 /* Acquire the lock */
157 KiAcquireSpinLock(&BootDriverLock
);
158 InbvOldIrql
= OldIrql
;
163 InbvReleaseLock(VOID
)
167 /* Capture the old IRQL */
168 OldIrql
= InbvOldIrql
;
170 /* Release the driver lock */
171 KiReleaseSpinLock(&BootDriverLock
);
173 /* If we were at dispatch level or lower, restore the old IRQL */
174 if (InbvOldIrql
<= DISPATCH_LEVEL
) KeLowerIrql(OldIrql
);
180 InbvEnableBootDriver(IN BOOLEAN Enable
)
182 /* Check if we're installed */
183 if (InbvBootDriverInstalled
)
185 /* Check for lost state */
186 if (InbvDisplayState
>= INBV_DISPLAY_STATE_LOST
) return;
188 /* Acquire the lock */
191 /* Cleanup the screen if we own it */
192 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
) VidCleanUp();
194 /* Set the new display state */
195 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
196 INBV_DISPLAY_STATE_DISABLED
;
198 /* Release the lock */
203 /* Set the new display state */
204 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
205 INBV_DISPLAY_STATE_DISABLED
;
211 InbvAcquireDisplayOwnership(VOID
)
213 /* Check if we have a callback and we're just acquiring it now */
214 if ((InbvResetDisplayParameters
) &&
215 (InbvDisplayState
== INBV_DISPLAY_STATE_LOST
))
217 /* Call the callback */
218 InbvResetDisplayParameters(80, 50);
221 /* Acquire the display */
222 InbvDisplayState
= INBV_DISPLAY_STATE_OWNED
;
227 InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned
)
229 /* Set the new display state */
230 InbvDisplayState
= DisplayOwned
? INBV_DISPLAY_STATE_OWNED
:
231 INBV_DISPLAY_STATE_LOST
;
236 InbvCheckDisplayOwnership(VOID
)
238 /* Return if we own it or not */
239 return InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
;
244 InbvGetDisplayState(VOID
)
246 /* Return the actual state */
247 return InbvDisplayState
;
252 InbvDisplayString(IN PCHAR String
)
254 /* Make sure we own the display */
255 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
257 /* If we're not allowed, return success anyway */
258 if (!InbvDisplayDebugStrings
) return TRUE
;
260 /* Check if a filter is installed */
261 if (InbvDisplayFilter
) InbvDisplayFilter(&String
);
263 /* Acquire the lock */
266 /* Make sure we're installed and display the string */
267 if (InbvBootDriverInstalled
) VidDisplayString((PUCHAR
) String
);
269 /* Print the string on the EMS port */
271 HeadlessCmdPutString
,
273 strlen(String
) + sizeof(ANSI_NULL
),
277 /* Release the lock */
284 /* We don't own it, fail */
290 InbvEnableDisplayString(IN BOOLEAN Enable
)
294 /* Get the old setting */
295 OldSetting
= InbvDisplayDebugStrings
;
298 InbvDisplayDebugStrings
= Enable
;
300 /* Return the old setting */
306 InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter
)
308 /* Save the filter */
309 InbvDisplayFilter
= Filter
;
314 InbvIsBootDriverInstalled(VOID
)
316 /* Return driver state */
317 return InbvBootDriverInstalled
;
322 InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback
)
324 /* Check if we're installed */
325 if (InbvBootDriverInstalled
)
327 /* Acquire the lock and cleanup if we own the screen */
329 if (InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
) VidCleanUp();
331 /* Set the reset callback and display state */
332 InbvResetDisplayParameters
= Callback
;
333 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
335 /* Release the lock */
340 /* Set the reset callback and display state */
341 InbvResetDisplayParameters
= Callback
;
342 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
348 InbvResetDisplay(VOID
)
350 /* Check if we're installed and we own it */
351 if ((InbvBootDriverInstalled
) &&
352 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
355 VidResetDisplay(TRUE
);
359 /* Nothing to reset */
365 InbvSetScrollRegion(IN ULONG Left
,
370 /* Just call bootvid */
371 VidSetScrollRegion(Left
, Top
, Width
, Height
);
376 InbvSetTextColor(IN ULONG Color
)
378 /* FIXME: Headless */
380 /* Update the text color */
381 VidSetTextColor(Color
);
386 InbvSolidColorFill(IN ULONG Left
,
392 /* Make sure we own it */
393 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
395 /* Acquire the lock */
398 /* Check if we're installed */
399 if (InbvBootDriverInstalled
)
402 VidSolidColorFill(Left
, Top
, Width
, Height
, (UCHAR
)Color
);
405 /* FIXME: Headless */
407 /* Release the lock */
415 InbvUpdateProgressBar(IN ULONG Progress
)
417 ULONG FillCount
, BoundedProgress
;
419 /* Make sure the progress bar is enabled, that we own and are installed */
420 if ((ShowProgressBar
) &&
421 (InbvBootDriverInstalled
) &&
422 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
424 /* Compute fill count */
425 BoundedProgress
= (InbvProgressState
.Floor
/ 100) + Progress
;
426 FillCount
= 121 * (InbvProgressState
.Bias
* BoundedProgress
) / 1000000;
428 /* Acquire the lock */
431 /* Fill the progress bar */
432 VidSolidColorFill(ProgressBarLeft
,
434 ProgressBarLeft
+ FillCount
,
438 /* Release the lock */
445 InbvBufferToScreenBlt(IN PUCHAR Buffer
,
452 /* Check if we're installed and we own it */
453 if ((InbvBootDriverInstalled
) &&
454 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
457 VidBufferToScreenBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
463 InbvBitBlt(IN PUCHAR Buffer
,
467 /* Check if we're installed and we own it */
468 if ((InbvBootDriverInstalled
) &&
469 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
471 /* Acquire the lock */
475 VidBitBlt(Buffer
, X
, Y
);
477 /* Release the lock */
484 InbvScreenToBufferBlt(IN PUCHAR Buffer
,
491 /* Check if we're installed and we own it */
492 if ((InbvBootDriverInstalled
) &&
493 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
496 VidScreenToBufferBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
502 InbvSetProgressBarCoordinates(IN ULONG Left
,
505 /* Update the coordinates */
506 ProgressBarLeft
= Left
;
507 ProgressBarTop
= Top
;
509 /* Enable the progress bar */
510 ShowProgressBar
= TRUE
;
515 InbvSetProgressBarSubset(IN ULONG Floor
,
519 ASSERT(Floor
< Ceiling
);
520 ASSERT(Ceiling
<= 100);
522 /* Update the progress bar state */
523 InbvProgressState
.Floor
= Floor
* 100;
524 InbvProgressState
.Ceiling
= Ceiling
* 100;
525 InbvProgressState
.Bias
= (Ceiling
* 100) - Floor
;
531 InbvIndicateProgress(VOID
)
535 /* Increase progress */
536 InbvProgressIndicator
.Count
++;
538 /* Compute new percentage */
539 Percentage
= min(100 * InbvProgressIndicator
.Count
/
540 InbvProgressIndicator
.Expected
,
542 if (Percentage
!= InbvProgressIndicator
.Percentage
)
544 /* Percentage has moved, update the progress bar */
545 InbvProgressIndicator
.Percentage
= Percentage
;
546 InbvUpdateProgressBar(Percentage
);
552 InbvGetResourceAddress(IN ULONG ResourceNumber
)
554 /* Validate the resource number */
555 if (ResourceNumber
> ResourceCount
) return NULL
;
557 /* Return the address */
558 return ResourceList
[ResourceNumber
--];
563 NtDisplayString(IN PUNICODE_STRING DisplayString
)
565 OEM_STRING OemString
;
567 /* Convert the string to OEM and display it */
568 RtlUnicodeStringToOemString(&OemString
, DisplayString
, TRUE
);
569 InbvDisplayString(OemString
.Buffer
);
570 RtlFreeOemString(&OemString
);
573 return STATUS_SUCCESS
;
579 DisplayBootBitmap(IN BOOLEAN TextMode
)
581 PVOID Header
, Band
, Text
, Screen
;
582 ROT_BAR_TYPE TempRotBarSelection
= RB_UNSPECIFIED
;
585 /* Check if the system thread has already been created */
586 if (SysThreadCreated
)
588 /* Reset the progress bar */
590 RotBarSelection
= RB_UNSPECIFIED
;
594 /* Check if this is text mode */
595 ShowProgressBar
= FALSE
;
598 /* Check if this is a server OS */
599 if (SharedUserData
->NtProductType
== NtProductWinNt
)
601 /* It's not, set workstation settings */
602 InbvSetTextColor(15);
603 InbvSolidColorFill(0, 0, 639, 479, 7);
604 InbvSolidColorFill(0, 421, 639, 479, 1);
607 Header
= InbvGetResourceAddress(IDB_LOGO_HEADER
);
608 Band
= InbvGetResourceAddress(IDB_LOGO_BAND
);
612 /* Set server settings */
613 InbvSetTextColor(14);
614 InbvSolidColorFill(0, 0, 639, 479, 6);
615 InbvSolidColorFill(0, 421, 639, 479, 1);
618 Header
= InbvGetResourceAddress(IDB_SERVER_HEADER
);
619 Band
= InbvGetResourceAddress(IDB_SERVER_BAND
);
622 /* Set the scrolling region */
623 InbvSetScrollRegion(32, 80, 631, 400);
625 /* Make sure we have resources */
626 if ((Header
) && (Band
))
628 /* BitBlt them on the screen */
629 InbvBitBlt(Band
, 0, 419);
630 InbvBitBlt(Header
, 0, 0);
635 /* Is the boot driver installed? */
637 if (!InbvBootDriverInstalled
) return;
639 /* Load the standard boot screen */
640 Screen
= InbvGetResourceAddress(IDB_BOOT_LOGO
);
641 if (SharedUserData
->NtProductType
== NtProductWinNt
)
643 /* Workstation product, display appropriate status bar color */
644 InbvGetResourceAddress(IDB_BAR_PRO
);
648 /* Display correct branding based on server suite */
649 if (ExVerifySuite(StorageServer
))
651 /* Storage Server Edition */
652 Text
= InbvGetResourceAddress(IDB_STORAGE_SERVER
);
654 else if (ExVerifySuite(ComputeServer
))
656 /* Compute Cluster Edition */
657 Text
= InbvGetResourceAddress(IDB_CLUSTER_SERVER
);
662 Text
= InbvGetResourceAddress(IDB_SERVER_LOGO
);
665 /* Server product, display appropriate status bar color */
666 InbvGetResourceAddress(IDB_BAR_SERVER
);
669 /* Make sure we had a logo */
672 /* Choose progress bar */
673 TempRotBarSelection
= RB_SQUARE_CELLS
;
675 /* Blit the background */
676 InbvBitBlt(Screen
, 0, 0);
678 /* Set progress bar coordinates and display it */
679 InbvSetProgressBarCoordinates(257, 352);
681 /* Check for non-workstation products */
682 if (SharedUserData
->NtProductType
!= NtProductWinNt
)
684 /* Overwrite part of the logo for a server product */
685 InbvScreenToBufferBlt(Buffer
, 413, 237, 7, 7, 8);
686 InbvSolidColorFill(418, 230, 454, 256, 0);
687 InbvBufferToScreenBlt(Buffer
, 413, 237, 7, 7, 8);
689 /* In setup mode, you haven't selected a SKU yet */
690 if (ExpInTextModeSetup
) Text
= NULL
;
694 /* Draw the SKU text if it exits */
695 if (Text
) InbvBitBlt(Text
, 180, 121);
697 /* Draw the progress bar bit */
698 // if (Bar) InbvBitBlt(Bar, 0, 0);
700 /* Set filter which will draw text display if needed */
701 InbvInstallDisplayStringFilter(DisplayFilter
);
704 /* Do we have a system thread? */
705 if (SysThreadCreated
)
707 /* We do, set the progress bar location */
709 RotBarSelection
= TempRotBarSelection
;
718 DisplayFilter(PCHAR
*String
)
720 /* Windows hack to skip first dots */
721 static BOOLEAN DotHack
= TRUE
;
723 /* If "." is given set *String to empty string */
724 if(DotHack
&& strcmp(*String
, ".") == 0)
729 /* Remove the filter */
730 InbvInstallDisplayStringFilter(NULL
);
734 /* Draw text screen */
735 DisplayBootBitmap(TRUE
);
742 FinalizeBootLogo(VOID
)
744 /* Acquire lock and check the display state */
746 if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED
)
748 /* Clear the screen */
749 VidSolidColorFill(0, 0, 639, 479, 0);
752 /* Reset progress bar and lock */