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 */
76 Status
= LdrAccessResource(LdrEntry
->DllBase
,
80 if (Data
) KiBugCheckData
[4] ^= RtlComputeCrc32(0, Data
, PAGE_SIZE
);
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
)
139 /* Check if we're at dispatch level or lower */
140 OldIrql
= KeGetCurrentIrql();
141 if (OldIrql
<= DISPATCH_LEVEL
)
143 /* Loop until the lock is free */
144 while (!KeTestSpinLock(&BootDriverLock
));
146 /* Raise IRQL to dispatch level */
147 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
150 /* Acquire the lock */
151 KiAcquireSpinLock(&BootDriverLock
);
152 InbvOldIrql
= OldIrql
;
157 InbvReleaseLock(VOID
)
161 /* Capture the old IRQL */
162 OldIrql
= InbvOldIrql
;
164 /* Release the driver lock */
165 KiReleaseSpinLock(&BootDriverLock
);
167 /* If we were at dispatch level or lower, restore the old IRQL */
168 if (InbvOldIrql
<= DISPATCH_LEVEL
) KeLowerIrql(OldIrql
);
173 InbvEnableBootDriver(IN BOOLEAN Enable
)
175 /* Check if we're installed */
176 if (InbvBootDriverInstalled
)
178 /* Check for lost state */
179 if (InbvDisplayState
>= INBV_DISPLAY_STATE_LOST
) return;
181 /* Acquire the lock */
184 /* Cleanup the screen if we own it */
185 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
) VidCleanUp();
187 /* Set the new display state */
188 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
189 INBV_DISPLAY_STATE_DISABLED
;
191 /* Release the lock */
196 /* Set the new display state */
197 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
198 INBV_DISPLAY_STATE_DISABLED
;
204 InbvAcquireDisplayOwnership(VOID
)
206 /* Check if we have a callback and we're just acquiring it now */
207 if ((InbvResetDisplayParameters
) &&
208 (InbvDisplayState
== INBV_DISPLAY_STATE_LOST
))
210 /* Call the callback */
211 InbvResetDisplayParameters(80, 50);
214 /* Acquire the display */
215 InbvDisplayState
= INBV_DISPLAY_STATE_OWNED
;
220 InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned
)
222 /* Set the new display state */
223 InbvDisplayState
= DisplayOwned
? INBV_DISPLAY_STATE_OWNED
:
224 INBV_DISPLAY_STATE_LOST
;
229 InbvCheckDisplayOwnership(VOID
)
231 /* Return if we own it or not */
232 return InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
;
237 InbvGetDisplayState(VOID
)
239 /* Return the actual state */
240 return InbvDisplayState
;
245 InbvDisplayString(IN PCHAR String
)
247 /* Make sure we own the display */
248 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
250 /* If we're not allowed, return success anyway */
251 if (!InbvDisplayDebugStrings
) return TRUE
;
253 /* Check if a filter is installed */
254 if (InbvDisplayFilter
) InbvDisplayFilter(&String
);
256 /* Acquire the lock */
259 /* Make sure we're installed and display the string */
260 if (InbvBootDriverInstalled
) VidDisplayString((PUCHAR
) String
);
262 /* Print the string on the EMS port */
264 HeadlessCmdPutString
,
266 strlen(String
) + sizeof(ANSI_NULL
),
270 /* Release the lock */
277 /* We don't own it, fail */
283 InbvEnableDisplayString(IN BOOLEAN Enable
)
287 /* Get the old setting */
288 OldSetting
= InbvDisplayDebugStrings
;
291 InbvDisplayDebugStrings
= Enable
;
293 /* Return the old setting */
299 InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter
)
301 /* Save the filter */
302 InbvDisplayFilter
= Filter
;
307 InbvIsBootDriverInstalled(VOID
)
309 /* Return driver state */
310 return InbvBootDriverInstalled
;
315 InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback
)
317 /* Check if we're installed */
318 if (InbvBootDriverInstalled
)
320 /* Acquire the lock and cleanup if we own the screen */
322 if (InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
) VidCleanUp();
324 /* Set the reset callback and display state */
325 InbvResetDisplayParameters
= Callback
;
326 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
328 /* Release the lock */
333 /* Set the reset callback and display state */
334 InbvResetDisplayParameters
= Callback
;
335 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
341 InbvResetDisplay(VOID
)
343 /* Check if we're installed and we own it */
344 if ((InbvBootDriverInstalled
) &&
345 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
348 VidResetDisplay(TRUE
);
352 /* Nothing to reset */
358 InbvSetScrollRegion(IN ULONG Left
,
363 /* Just call bootvid */
364 VidSetScrollRegion(Left
, Top
, Width
, Height
);
369 InbvSetTextColor(IN ULONG Color
)
371 /* FIXME: Headless */
373 /* Update the text color */
374 VidSetTextColor(Color
);
379 InbvSolidColorFill(IN ULONG Left
,
385 /* Make sure we own it */
386 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
388 /* Acquire the lock */
391 /* Check if we're installed */
392 if (InbvBootDriverInstalled
)
395 VidSolidColorFill(Left
, Top
, Width
, Height
, (UCHAR
)Color
);
398 /* FIXME: Headless */
400 /* Release the lock */
407 InbvUpdateProgressBar(IN ULONG Progress
)
409 ULONG FillCount
, BoundedProgress
;
411 /* Make sure the progress bar is enabled, that we own and are installed */
412 if ((ShowProgressBar
) &&
413 (InbvBootDriverInstalled
) &&
414 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
416 /* Compute fill count */
417 BoundedProgress
= (InbvProgressState
.Floor
/ 100) + Progress
;
418 FillCount
= 121 * (InbvProgressState
.Bias
* BoundedProgress
) / 1000000;
420 /* Acquire the lock */
423 /* Fill the progress bar */
424 VidSolidColorFill(ProgressBarLeft
,
426 ProgressBarLeft
+ FillCount
,
430 /* Release the lock */
437 InbvBufferToScreenBlt(IN PUCHAR Buffer
,
444 /* Check if we're installed and we own it */
445 if ((InbvBootDriverInstalled
) &&
446 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
449 VidBufferToScreenBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
455 InbvBitBlt(IN PUCHAR Buffer
,
459 /* Check if we're installed and we own it */
460 if ((InbvBootDriverInstalled
) &&
461 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
463 /* Acquire the lock */
467 VidBitBlt(Buffer
, X
, Y
);
469 /* Release the lock */
476 InbvScreenToBufferBlt(IN PUCHAR Buffer
,
483 /* Check if we're installed and we own it */
484 if ((InbvBootDriverInstalled
) &&
485 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
488 VidScreenToBufferBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
494 InbvSetProgressBarCoordinates(IN ULONG Left
,
497 /* Update the coordinates */
498 ProgressBarLeft
= Left
;
499 ProgressBarTop
= Top
;
501 /* Enable the progress bar */
502 ShowProgressBar
= TRUE
;
507 InbvSetProgressBarSubset(IN ULONG Floor
,
511 ASSERT(Floor
< Ceiling
);
512 ASSERT(Ceiling
<= 100);
514 /* Update the progress bar state */
515 InbvProgressState
.Floor
= Floor
* 100;
516 InbvProgressState
.Ceiling
= Ceiling
* 100;
517 InbvProgressState
.Bias
= (Ceiling
* 100) - Floor
;
522 InbvIndicateProgress(VOID
)
526 /* Increase progress */
527 InbvProgressIndicator
.Count
++;
529 /* Compute new percentage */
530 Percentage
= min(100 * InbvProgressIndicator
.Count
/
531 InbvProgressIndicator
.Expected
,
533 if (Percentage
!= InbvProgressIndicator
.Percentage
)
535 /* Percentage has moved, update the progress bar */
536 InbvProgressIndicator
.Percentage
= Percentage
;
537 InbvUpdateProgressBar(Percentage
);
543 InbvGetResourceAddress(IN ULONG ResourceNumber
)
545 /* Validate the resource number */
546 if (ResourceNumber
> ResourceCount
) return NULL
;
548 /* Return the address */
549 return ResourceList
[ResourceNumber
--];
554 NtDisplayString(IN PUNICODE_STRING DisplayString
)
556 OEM_STRING OemString
;
558 /* Convert the string to OEM and display it */
559 RtlUnicodeStringToOemString(&OemString
, DisplayString
, TRUE
);
560 InbvDisplayString(OemString
.Buffer
);
561 RtlFreeOemString(&OemString
);
564 return STATUS_SUCCESS
;
569 DisplayBootBitmap(IN BOOLEAN SosMode
)
571 PVOID Header
, Band
, Text
, Screen
;
572 ROT_BAR_TYPE TempRotBarSelection
= RB_UNSPECIFIED
;
575 /* Check if the system thread has already been created */
576 if (SysThreadCreated
)
578 /* Reset the progress bar */
580 RotBarSelection
= RB_UNSPECIFIED
;
584 /* Check if this is SOS mode */
585 ShowProgressBar
= FALSE
;
588 /* Check if this is a server OS */
589 if (SharedUserData
->NtProductType
== NtProductWinNt
)
591 /* It's not, set workstation settings */
592 InbvSetTextColor(15);
593 InbvSolidColorFill(0, 0, 639, 479, 7);
594 InbvSolidColorFill(0, 421, 639, 479, 1);
597 Header
= InbvGetResourceAddress(IDB_LOGO_HEADER
);
598 Band
= InbvGetResourceAddress(IDB_LOGO_BAND
);
602 /* Set server settings */
603 InbvSetTextColor(14);
604 InbvSolidColorFill(0, 0, 639, 479, 6);
605 InbvSolidColorFill(0, 421, 639, 479, 1);
608 Header
= InbvGetResourceAddress(IDB_SERVER_HEADER
);
609 Band
= InbvGetResourceAddress(IDB_SERVER_BAND
);
612 /* Set the scrolling region */
613 InbvSetScrollRegion(32, 80, 631, 400);
615 /* Make sure we have resources */
616 if ((Header
) && (Band
))
618 /* BitBlt them on the screen */
619 InbvBitBlt(Band
, 0, 419);
620 InbvBitBlt(Header
, 0, 0);
625 /* Is the boot driver installed? */
627 if (!InbvBootDriverInstalled
) return;
629 /* Load the standard boot screen */
630 Screen
= InbvGetResourceAddress(IDB_BOOT_LOGO
);
631 if (SharedUserData
->NtProductType
== NtProductWinNt
)
633 /* Workstation product, display appropriate status bar color */
634 InbvGetResourceAddress(IDB_BAR_PRO
);
638 /* Display correct branding based on server suite */
639 if (ExVerifySuite(StorageServer
))
641 /* Storage Server Edition */
642 Text
= InbvGetResourceAddress(IDB_STORAGE_SERVER
);
644 else if (ExVerifySuite(ComputeServer
))
646 /* Compute Cluster Edition */
647 Text
= InbvGetResourceAddress(IDB_CLUSTER_SERVER
);
652 Text
= InbvGetResourceAddress(IDB_SERVER_LOGO
);
655 /* Server product, display appropriate status bar color */
656 InbvGetResourceAddress(IDB_BAR_SERVER
);
659 /* Make sure we had a logo */
662 /* Choose progress bar */
663 TempRotBarSelection
= RB_SQUARE_CELLS
;
665 /* Blit the background */
666 InbvBitBlt(Screen
, 0, 0);
668 /* Set progress bar coordinates and display it */
669 InbvSetProgressBarCoordinates(257, 352);
671 /* Check for non-workstation products */
672 if (SharedUserData
->NtProductType
!= NtProductWinNt
)
674 /* Overwrite part of the logo for a server product */
675 InbvScreenToBufferBlt(Buffer
, 413, 237, 7, 7, 8);
676 InbvSolidColorFill(418, 230, 454, 256, 0);
677 InbvBufferToScreenBlt(Buffer
, 413, 237, 7, 7, 8);
679 /* In setup mode, you haven't selected a SKU yet */
680 if (ExpInTextModeSetup
) Text
= NULL
;
684 /* Draw the SKU text if it exits */
685 if (Text
) InbvBitBlt(Text
, 180, 121);
687 /* Draw the progress bar bit */
688 // if (Bar) InbvBitBlt(Bar, 0, 0);
691 /* Do we have a system thread? */
692 if (SysThreadCreated
)
694 /* We do, set the progress bar location */
696 RotBarSelection
= TempRotBarSelection
;
704 FinalizeBootLogo(VOID
)
706 /* Acquire lock and check the display state */
708 if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED
)
710 /* Clear the screen */
711 VidSolidColorFill(0, 0, 639, 479, 0);
714 /* Reset progress bar and lock */