If you’ve used Azure Canvas before, you’ll notice it’s had a rebrand — it’s now ZoneForge for Azure, and it’s moved to zoneforge.cloud. Everything else about it is the same free, in-browser tool; the name is the main thing that’s changed. (azure-canvas.com still redirects, and all your existing share links keep working.)
Why the rename? Microsoft recently shipped a feature called “Azure Canvases”, which started crowding out the tool in search results and causing confusion. Rather than fight Microsoft’s own product for the name — and to keep on the right side of the “Azure” trademark, which asks third-party tools to use a “X for Azure” pattern — I’ve rebranded. “ZoneForge” felt right: the tool is increasingly about defining and forging the zones (subscriptions, regions, resource groups, networks) of an architecture.
It’s grown well beyond a diagram tool. What started as “drag some Azure shapes and generate Bicep” is now closer to a proper Azure-aware architecture designer. Since the original post it’s added:
Import from Azure — point it at a subscription and pull in an entire resource group (or a single VNet and what’s connected to it) to diagram what you already run.
Architecture-aware placement — it understands Azure, so resources snap into the right containers: subnets inside VNets, VMs/NSGs inside subnets, gateways/firewalls/bastion in their reserved subnets.
Validate, Review & Well-Architected score — check the design against a live subscription, plus best-practice review and a WAF pillar score.
Live cost estimate — real Azure retail pricing straight on the canvas, no sign-in needed.
Boundaries & views — Management Group / Subscription / Region / Resource Group boundaries, plus separate Network, Infrastructure and Identity views.
More ways to get the design out — Bicep, ARM JSON and Terraform, plus Visio (.vsdx), SVG, and clean A4 printing.
Quality of life — a File menu (save/load/import/export), one-click Share links, draggable dialogs, and dark mode.
Under the hood the rename touches everything you’d expect — new domain, updated metadata, new export filenames (zoneforge.bicep, zoneforge.arm.json, etc.) — but it’s deliberately backwards-compatible. Old Azure Canvas JSON exports still import, the #d= share-link format is unchanged, and your saved diagrams survive.
There’s also now a feedback box in the About dialog (a 5-star rating and a comment field) — if you’ve tried it, I’d genuinely love a rating and a line on what worked or what broke. Just click the ‘Z’ in the top right corner.
It’s still free, still runs entirely in your browser, and still at the stage where I want people to poke at it. Give it a go and tell me what you think.
When I first wrote about Azure Canvas, the easy pitch was “draggable Azure icons in your browser.” That was never the point, and the gap between the two has widened considerably since. Azure Canvas is not a diagramming tool that happens to use Azure shapes — it is an architecture designer that understands what those shapes mean, what they are allowed to do, and whether Azure will actually accept them.
The distinction matters, because anyone can push coloured rectangles around a canvas. The hard part is a canvas that pushes back.
As ever, the tool is free and runs entirely in the browser.
Every object in Azure Canvas carries the rules of the real service behind it, and the canvas enforces them as you design:
– VNets contain subnets; VMs, NSGs, route tables, NAT gateways, private endpoints, and Application Gateways live inside subnets rather than floating in space.
– VPN Gateway, Azure Bastion, and Azure Firewall claim their required reserved subnets automatically, because Azure insists on them and so should the diagram.
– Peerings, VPN connections, public IP associations, identities, monitoring links, and application dependencies are modelled as real relationships, not decorative arrows.
– Service‑specific obligations are handled for you — an NSG sharing a subnet with Application Gateway v2 gets its GatewayManager rule without you needing to remember it at 11pm.
The result is a design that is structurally correct by construction. You are not drawing a picture of an architecture; you are building the architecture, and the picture is a side effect.
From design to validated to deployed
The reason the modelling matters is that the diagram is the start of a pipeline, not the end of one:
– Import reconstructs an existing resource group or VNet and its connected resources directly from Azure Resource Manager, read‑only, with subscription and region boundaries intact.
– Validate Design combines local structural checks with live Azure checks — provider registration, region and VM‑size availability, storage name availability, CIDR overlap, required relationships, and service constraints — so problems surface before deployment, not during it.
– Generate produces deployable Bicep, ARM JSON, and a Terraform starter from the same model.
– Deploy submits the generated template straight to Azure Resource Manager, no local CLI or compiler required, and monitors progress with the timing warnings that gateways and Bastion have taught it to give.
Each stage reads from one architecture‑aware model. That is what separates this from a drawing app: the boxes are not the artifact, they are the source of truth that everything else is derived from.
Taking the design elsewhere
Because the model is real, the outputs are too. Alongside JSON import/export and browser‑local saving, Azure Canvas can now hand your design to the places architectures tend to end up — exporting to native Visio for design packs that have to live in someone else’s document, and printing a design that crops, scales, and fits itself to the page instead of fighting you. Useful, unglamorous, and firmly in service of the design rather than the headline.
Who it’s for
Azure Canvas is for architects, network and security teams, engineers, and students — anyone who prefers to understand an environment visually before committing it to code, and who wants the visual to be more than a pretty guess.
It is free, actively evolving, and shaped by people designing and operating real Azure environments. Suggestions are welcome in the comments; I read them, and Azure remains an enthusiastic reviewer of the rest.
In case you’ve been living under a rock, OSDCloud is a PowerShell-based tool that rebuilds a Windows device from scratch using WinPE. It downloads Windows and drivers from Microsoft and OEM sources, making it an effective offline recovery solution for Intune-managed devices. Written by David Segura (several years ago now!) it has recently been brought under the Recast umbrella. See About OSDCloud | OSDCloud by Recast for more information on the official site.
This is a great module but I have struggled a bit in the past with the site’s documentation. Although there is a lot of it (good) I have found that it’s not always terribly linear in its presentation. Recently I had a possible rescue scenario I wanted to implement which would require a full offline OS Autopilot recovery. OSDCloud is a tool that can address this and I wanted to put together a quick no-nonsense, step-by-step document to produce a fully self-contained USB drive. The OS image and driver pack are stored on the USB itself, so no internet connection is required during recovery.
Note – I have tailored this for a low-end Dell laptop but please change parameters where necessary to cater for Lenovo, HP or any other device driver packs.
What You Need
A Windows 10 or Windows 11 PC with admin rights (the ‘build PC’)
Internet access on the build PC to download tools and content
A USB flash drive, 16 GB or larger (recommended: Samsung BAR or Samsung FIT) — all data will be erased
The Windows ADK and Windows PE add-on installed on the build PC
Part 1 — Install the Windows ADK
The Windows Assessment and Deployment Kit (ADK) is required to build the WinPE boot environment. Install this on your build PC (the physical Windows host).
Step 1 — Download and install the ADK
Go to the Microsoft ADK download page and install both components:
Windows Assessment and Deployment Kit — select Deployment Tools only
Windows PE add-on for the ADK (a separate download on the same page)
Run all commands in this section in PowerShell as Administrator.
Step 2 — Install the OSD PowerShell module
Set-ExecutionPolicy RemoteSigned -Force
Install-Module OSD -Force
Step 3 — Create the OSDCloud template and workspace
Import-Module OSD -Force
New-OSDCloudTemplate
New-OSDCloudWorkspace -WorkspacePath C:\OSDCloud
Part 3 — Build WinPE and Create the USB
Step 4 — Build WinPE with drivers and auto-install startup
This command builds the WinPE boot image, injects cloud drivers, and configures WinPE to automatically begin installing Windows 11 25H2 when booted — with no prompts or confirmations required.
Wi-Fi and all other device drivers are included in the Dell driver pack added to the USB in Step 7. OSDCloud applies these during recovery, so drivers will be fully functional by the time the device reaches OOBE.
⚠ Note: Every time you run Edit-OSDCloudWinPE, the startup resets to default first. Always include all parameters (-CloudDriver, -StartPSCommand) in a single command.
⚠ Warning: The -ZTI and -Restart flags mean the USB will immediately and silently wipe and reinstall Windows with no confirmation. Only boot from this USB on a device you intend to rebuild.
Step 5 — Plug in the USB drive
Insert the USB drive into the build PC. All data on it will be erased in the next step.
Step 6 — Create the OSDCloud USB
New-OSDCloudUSB
You will be shown a list of USB drives. Enter the DiskNumber of your USB drive and confirm when prompted. OSDCloud will erase, partition, and format the drive with two partitions: a large NTFS partition for OSDCloud data and a small 2 GB FAT32 partition for WinPE boot.
Part 4 — Add the OS and Drivers to the USB
These steps add the offline content to the USB so no internet connection is needed during recovery.
Step 7 — Add the Dell driver pack
This downloads the driver pack for your specific Dell model and stores it on the USB. A GridView window will appear — find and select your model (PC14255) and click OK.
Update-OSDCloudUSB -DriverPack Dell
To download the driver pack for whichever PC you are currently running the command on:
This downloads the Windows 11 25H2 en-gb ESD file (~4-5 GB) and saves it to the USB. This may take some time depending on your connection speed.
⚠ Note: Note the difference in OSName format: Update-OSDCloudUSB uses “Windows 11 25H2” (no x64), while Start-OSDCloud uses “Windows 11 25H2 x64”. Using the wrong format will produce a parameter validation error.
Part 5 — Keeping the USB Up to Date
Run the following on the host PC whenever you want to refresh the USB content. You do not need to return to the Hyper-V VM unless you are rebuilding WinPE from scratch.
If you have rebuilt WinPE (re-run Edit-OSDCloudWinPE), push the updated WinPE to the USB:
Update-OSDCloudUSB
Restore a workspace from the USB
If you need to update the USB from a new PC that does not have a workspace, you can restore one directly from the USB:
New-OSDCloudWorkspace -fromUsbDrive
Part 6 — Recovering a Device
Step 9 — Boot the target device from the USB
Insert the USB into the device to be recovered
Power on and press the boot menu key — F12 on most Dell devices
Select the OSDCloud USB drive from the boot menu
Step 10 — Automatic installation
WinPE will load and OSDCloud will begin immediately with no prompts. It will:
Read the Windows 11 25H2 OS image from the USB
Apply the Dell driver pack from the USB
Install Windows to the internal drive
Reboot automatically when complete
The device will boot to the Windows Out-of-Box Experience (OOBE) and can be enrolled into Intune/Autopilot as normal.
⚠ Note: Recovery is fully offline. No internet connection is required. Firmware updates and Autopilot module downloads (which do require internet) are skipped in this configuration. These can be applied after enrolment via Intune.
I have mentioned elsewhere that I might look into a version of space invaders in another language, most likely Python…however I woke up one night at 3AM with a different idea and figured a drag and drop Azure networking app would be a better use of my time.
Well, it’s debatable – I have deliberatly not looked to see if there are other applications like this around but I would virtually guarantee if I did then I’d find some. Feel free to add any you recommend in the comments. Nonetheless it isn’t the point. I wanted to do this myself and although it is still a work in progress I am happy with that progress so far.
This is version 1.0 and is a C#/WPF based app which allows you to design your network by dragging items from the toolbox on the left. You can right-click to update the properties of those objects once they are on the ‘canvas’ adding extra subnets if they’re vnets, OS versions/sizes/disk types etc if they VMs, zone redundancy, route types etc if they’re gateways, etc – you get the picture.
Objects ‘snap’ to the grid and snap to their respective vNets. The app will ensure that IP ranges don’t overlap and names aren’t duplicated. When you’re happy, if you’ve authenticated with your tenant, you can hit the ‘validate’ button to ensure it complies with what is actually available in Azure, eg some locations may not support certain VM sizings for example. If you don’t have access to log into your tenant then that’s fine too – the app provides some standard defaults.
Once you’re happy with what you have, hit one of the ‘generate’ buttons – Bicep or JSON to create an IaC template that you can import into your tenant and create the resources as you have designed them. Remember to save your diagram if you want to tweak it later.
As I say, this is a work in progress and there is still a lot of tools it is missing. Feel free to download the code from github and add new tools. I may do the same but I already have a 2.0 in the pipeline which is an HTML 5-based app which can be run direct from the web. This is also in the repo if you poke around but it is still in testing and requires more work. I will post here when I’m a bit further down the line on this one but it currently lacks a bit of the polish of this version, something that will be fixed in due course.
As promised, the “much anticipated” follow-up to ‘Hello World‘ in assembly. I’m trying to pick simple topics to show how this works so I make no apologies for the somewhat bland output, in this case, a square. I did make it a yellow square though.
Again, this is all written with the BBC Micro assembler so you will see hexadecimal notation indicated with an & instead of a $ like you may see in other assemblers.
Before we dive in, I need to describe how commands Plot, Draw and VDU work on the BBC. The BBC Micro’s DRAW command in BASIC is actually implemented using the same VDU command system as PLOT.
When you use DRAW x,y in BASIC, it internally:
Converts to absolute screen coordinates
Issues a PLOT 85, x, y command (or similar PLOT code)
This PLOT command then generates a sequence of VDU commands
The similarity works like this:
DRAW → PLOT → VDU sequence
For example, PLOT 85, x, y (draw absolute line) becomes something like:
VDU 25, 85, x MOD 256, x DIV 256, y MOD 256, y DIV 256
So all three commands (DRAW, PLOT, VDU) are essentially layers of the same system:
VDU is the lowest level – sends bytes directly to the VDU driver
PLOT is a mid-level wrapper that formats graphics commands into VDU sequences (VDU 25 specifically)
DRAW is a high-level BASIC convenience command that translates to PLOT commands
This layered approach meant the 6502 assembly implementation could reuse the same VDU driver code for all graphics operations, with BASIC commands simply being syntactic sugar that is ultimately funneled down to VDU byte sequences.
Straight into the code. Don’t be scared off by the length – this makes it easier to understand.
10 REM BBC Micro 6502 Assembly Program to Draw a Square
20 REM Uses OS graphics routines to draw a square on screen
30 REM Type RUN to execute
40
50 oswrch=&FFEE
60
70 FOR pass=0 TO 2 STEP 2
80 P%=&1000
90 [
100 OPT pass
110
120 .start
130 LDA #22 ; VDU 22 - set screen mode
140 JSR oswrch
150 LDA #1 ; Mode 1
160 JSR oswrch
170
180 LDA #16 ; VDU 16 - clear graphics area
190 JSR oswrch
200
210 LDA #29 ; VDU 29 - set graphics origin
220 JSR oswrch
230 LDA #0 ; X origin (low byte)
240 JSR oswrch
250 LDA #2; X origin (high byte)
260 JSR oswrch
270 LDA #0 ; Y origin (low byte)
280 JSR oswrch
290 LDA #2; Y origin (high byte)
300 JSR oswrch
310
320 LDA #18 ; VDU 18 - set graphics color
330 JSR oswrch
340 LDA #0; GCOL action (normal plotting)
350 JSR oswrch
360 LDA #2; Color 2 (Yellow in mode 1)
370 JSR oswrch
380
390 LDA #25 ; VDU 25 - PLOT command
400 JSR oswrch
410 LDA #4; PLOT 4 - move to absolute coordinates
420 JSR oswrch
430 LDA #&CE ; X = -50 (low byte)
440 JSR oswrch
450 LDA #&FF ; X = -50 (high byte)
460 JSR oswrch
470 LDA #200 ; Y = 50 (low byte)
480 JSR oswrch
490 LDA #0; Y = 50 (high byte)
500 JSR oswrch
510
520 LDA #25 ; VDU 25 - PLOT command
530 JSR oswrch
540 LDA #5; PLOT 5 - draw line to absolute coordinates
550 JSR oswrch
560 LDA #200 ; X = 50 (low byte)
570 JSR oswrch
580 LDA #0; X = 50 (high byte)
590 JSR oswrch
600 LDA #200 ; Y = 50 (low byte)
610 JSR oswrch
620 LDA #0; Y = 50 (high byte)
630 JSR oswrch
640
650 LDA #25 ; VDU 25 - PLOT command
660 JSR oswrch
670 LDA #5 ; PLOT 5 - draw line to absolute coordinates
680 JSR oswrch
690 LDA #200 ; X = 50 (low byte)
700 JSR oswrch
710 LDA #0; X = 50 (high byte)
720 JSR oswrch
730 LDA #&CE ; Y = -50 (low byte)
740 JSR oswrch
750 LDA #&FF ; Y = -50 (high byte)
760 JSR oswrch
770
780 LDA #25 ; VDU 25 - PLOT command
790 JSR oswrch
800 LDA #5; PLOT 5 - draw line to absolute coordinates
810 JSR oswrch
820 LDA #&CE ; X = -50 (low byte)
830 JSR oswrch
840 LDA #&FF ; X = -50 (high byte)
850 JSR oswrch
860 LDA #&CE ; Y = -50 (low byte)
870 JSR oswrch
880 LDA #&FF ; Y = -50 (high byte)
890 JSR oswrch
900
910 LDA #25 ; VDU 25 - PLOT command
920 JSR oswrch
930 LDA #5; PLOT 5 - draw line to absolute coordinates
940 JSR oswrch
950 LDA #&CE ; X = -50 (low byte)
960 JSR oswrch
970 LDA #&FF ; X = -50 (high byte)
980 JSR oswrch
990 LDA #200 ; Y = 50 (low byte)
1000 JSR oswrch
1010 LDA #0; Y = 50 (high byte)
1020 JSR oswrch
1030 RTS
1120 ]
1130 NEXT pass
1170 CALL &1000
FURTHER EXPLANATION:
Hopefully the explanation on how it is working in a similar fashion to BASIC’s VDU command above helps describe how the line is drawn.
You will notice we call the OS Write Character routine after each change. This essentially tells the OS we are writing to the screen.
We have the concept of ‘low byte’ and ‘high byte’ because we are talking about an 8-bit system which can’t handle numbers greater than 255 (0-255). Since the mode 1 screen is 320 pixels this is obviously higher than 255. In this case, low byte refers to 1-127 when we consider it as binary (11111111 = 256 dec) and high byte is the next byte along starting at 5.
As with anything, best to test for yourself. I do most of my testing/playing using the excellent BeebEm. There are probably (almost certainly) better ways to accomplish this so feel free to post any comments with improvements. I don’t pretend to be an expert here by any stretch, merely trying to explain how BASIC maps to machine language for simple tasks.
I was trying to enroll a laptop in Intune and kept getting the above message popping up. The laptop was Windows 11 25H2 so why wouldn’t it have an up-to-date browser installed? Complete nonsense.
To fix this issue, this is what I did:
If not done already, ensure you have a command prompt up (shift-F10/Shift-fn-F10)
CD C:\Program Files (x86)\microsoft\Edge\Application
I am not a developer by trade and any experience I have is of using C# and various iterations of Visual Basic in the distant (7+ years) past. I use PowerShell in my day-to-day but this can’t really be described as a genuine programming language. One of my ‘bucket list’ items for 2025 was to figure out how to write a Space Invaders game and something I have been procrastinating over for months. This was mainly a project in how do I write it but also served as a great way to learn or at least re-acquaint myself with a programming language I’d lost touch with. Since this was to be a fairly steep learning curve, I figured I should give myself a fighting chance by choosing a language that :
I am somewhat familiar with
Is suitable for such a project.
So for part 1, C# it was. I say part 1 because now I have a good idea of how to put the game together, I would like to take this further and write a version in another language and possibly even a recognizable version in PowerShell. This should give me some exposure to other languages I currently have little to no knowledge of (I’m looking at you, C++ and Python).
But you can get AI to write the whole thing, surely? Well, yes, true and I’m not going to lie, to some extent, using AI is almost unavoidable. When starting on a particular subroutine it would basically read my mind about what I wanted to do next. Really. It’s not like I’m new to this (AI in general or looking for fixes to programming issues) but I’d start to type the name of a routine to make the saucer fly across the screen and it would largely write the thing for me before I’d finished typing the name of the sub. Blown away. That said, not everything was quite right and many times its assumptions weren’t what I wanted so going through the code to fix these issues wasn’t just ‘satisfying’ but necessary.
Then there were annoyances which I genuinely wanted AI to solve but try as it might, it just couldn’t. First versions occasionally left artifacts of the laser fire on the screen that wouldn’t go away. Co-Pilot kept making suggestions but either these didn’t work or worse still, broke the code. And it was during these frustrating times that my free access ran out and I was left to fend for myself (more or less). Back to Stack Overflow for fixes (in the end this solved itself when I was forced to adopt the OnPaint method for sprites – more on this later).
Eventually I had a working game on my desktop development machine which I was quite proud of. It looked just like the real thing and although I’d furnished it with a few more flourishes than I’d originally planned (my starting goal was to make a very basic game that could be ported easily from language to language) I was happy with it. Then I tried it on my laptop. Oh dear. Every time I fired a laser it slowed the game down. Sound was also hogging the UI thread too…my God, this computer must be several million times the speed (and memory) of my old Beeb that used to run this game, so why is it having such a hard time?
This called for a re-write to some extent. Quite a large extent, in fact. I had to put the main game loop on a background thread; the sound had to be pushed out onto a background thread too (this helped a lot but still isn’t perfect by any stretch). However the really big change was to replace the way the sprites were presented. My initial version had all graphics as a separate PictureBox – this was ideal as it was simple and would potentially make future versions eas(ier) to write. Unfortunately this proved incredibly resource-intensive and although it ran OK on my desktop machine, it really struggled on my laptop. Begrudgingly I had to bite the bullet and swap this for the OnPaint Method. Although the learning curve for this increased (dramatically in fact), this did have two main advantages:
The OnPaint method is significantly more performant. Each PictureBox is a full windowed control, which means it has its own window handle (HWND) and processes system messages. For a game with lots of objects like aliens, bullets, and lasers, creating and managing a PictureBox for each one consumes substantial system resources and this led to poor performance and noticeable lag, esp on my laptop. In contrast, OnPaint performs a single, highly optimized drawing operation directly onto the form.
Smooth Animation (Double Buffering): The OnPaint method works seamlessly with the form’s DoubleBuffered property. By setting this.DoubleBuffered = true;, all drawing operations within OnPaint are first rendered to an off-screen buffer and then drawn to the screen in a single operation. This improved animation noticeably.
There are other benefits to this too which I’ll leave out here for brevity’s sake and ultimately it was worth the effort to get the game working with this method instead. The PictureBox version can be found here and the OnPaint version here. Links to the full project are also at the end. I still think there is value in the PictureBox (and single threaded) version if only as the academic exercise of creating the game in it’s simplest* form.
*It’s not in it’s simplest form. I could have made it a lot simpler. As I said, I got a little carried away.
GAME FLOW
Although I won’t pretend I started out with a ‘design’ in mind, this is something that kind of presented itself as I got further into the project. I have used VS2022’s Mermaid Editor extension to help create a flow diagram of how the whole thing works:
I have, somewhat lazily, embedded the flying saucer as a project resource and this is the only graphic in the project that remains as a PictureBox. So in short, this is on the form and not ‘created’ in code. The same can be said for the hi-score form which I have designed in the editor rather than created in code. I make no apologies for this and feel free to change and use what you like for your own project, should you wish to. All the graphic and sound files will, as a result, need to be in the same directory as the exe file (“EalingAttack.exe“). Oh yes and on that subject, I had various names for it throughout the project. It started with a reference to my road (BirkbeckInvaders) before eventually settling for EalingAttack (my borough in London). As such you’ll see references to these and they could do with cleaning up in an ideal world. Finally, I have added descriptions of what everything does throughout the code for anyone who’s interested.
I haven’t decided when the next installment will be yet but don’t hold your breath. Ideally I need to start spending some time with the family again :-). I promised a follow-up article on 6502 assembly as well which I still haven’t got round to yet. I’ll probably tackle that first though as it will be a shorter project but again, in my own time which could be whenever.
CONTROLS:
Oh and I forgot to add a controls screen so it’s:
Left/Right arrow for the turret movement and spacebar to fire. As alluded to above, sound is still an issue on some machines, particularly the background sound. If this noticeably affects gameplay, you can toggle it by pressing ‘S‘.
Finally – feel free to create your own upgrades and leave links in the comments.
Either clone it or for those who just want to play the game go to Code > Download zip, unpack and run the exe. I promise, there are no nasty surprises (apart from the bad coding).
Late edit – found one or two bugs which could do with fixing (should be easy enough!). Get to level 6 and see what I mean. High score table needs some finessing too.
Quick and dirty web version. This is notable only for the fact it runs in an Azure Container Instance. If the link doesn’t work then I’ve probably deactivated the CI.
I recently had an issue at work where we saw a not-insignificant number of our Z4G5 workstations regularly going into recovery mode after the weekly reboot. As far as we were aware at the time, they were configured no differently to any of our other computers, laptop desktop or mini-workstation, so this was confusing. What follows is what worked for us and depending on your environment, you might have other restrictions or security settings.
Following some digging, we discovered that these machines had a different PCR Validation Profile. Most of our machines are set to 7,11 whereas these were set 0,2,4,11. You can check the validation profile of a machine with the following command:
Manage-bde -protectors -get C:
Where C: is the drive letter.
SOLUTION:
We also noticed that Pre-Boot DMA Protection was turned off in the BIOS on these workstations. We turned this setting back on, cleared the TPM and restarted the machine. This reset the protectors back to 7,11 and the machines now continue to boot normally.
I appreciate there is an element missing here – why was it entering recovery mode in the first place? In many instances, 0,2,4,11 is a perfectly acceptable default. Truth is at the moment, this is still unclear and HP weren’t able to provide a good explanation here either but a clue might lie in the last paragraph in the link below (re ‘Secure Boot validation’).
FURTHER INFO:
Indices can be configured via registry/GPO policy. Briefly, the default PCRs used by BitLocker in the BIOS are 0, 2, 4, 8, 9, 10, 11:
PCR0: Dynamic Root of Trust, BIOS Code, Platform Extensions
PCR2: ROM Code
PCR4: MBR Code
PCR8: NTFS Boot Sector
PCR9: NTFS Boot Block
PCR10: NTFS Boot Manager
PCR11: BitLocker’s Volume Master Key (VMK) and its critical components
I anticipate writing occasional posts about BBC Micro machine code as I do harbour a fascination with this from all those years back as a 12 year old. Let’s start with something basic (or rather machine code, ho ho).
I think I probably speak for everyone when I say my first introduction to BASIC was writing something along the lines of:
10 PRINT "Simon Rules!" 20 GOTO 10
…to be greeted with my message endlessly scrolling down the screen. Happy days. It makes sense then to create the same in assembly language as an introduction then, surely? 🙂
In the traditions of this site, I will try keep it concise and to the point but as you can see below, in ASM you really have to tell the machine exactly what you need it to do – no simple instructions to simply write what you choose. Don’t worry though, explanations will follow. Here is the exact equivalent in ASM of what we just did above in BASIC:
Line 20: P% represents the place in memory where the program will be run from and refers to the ‘stack pointer’. This is a built in variable and we will be running the program from &2000 in this case. Note: ‘&’ is used to denote hexadecimal notation will follow – many other machines at the time (and to this day for that matter) use the ‘$’ for this.
Line 30 and 130: All assembly code on the Beeb needs to be encased in square brackets.
Line 35: .helloworld marks the start of the function we use to define our output.
Line 36: On the BBC Micro, EQUS stands for Equate String and essentially reserves a piece of memory containing the string specified.
Line 37: On the BBC Micro EQUB stands for Equate Byte and essentially reserves a piece of memory containing the byte specified. So what’s &A ? This translates to decimal ’10’ and is the ASCII for the newline character. This will be processed after ‘Hello World!’
Line 38: As above but what’s &D ? This translates to decimal ’13’ and is the ASCII for the Carriage Return character. This will be processed after newline above and these two additions ensure anything printed subsequently is on a new line.
Line 40:.print marks the start of the routine we use to loop through and print our output.
Line 50: This loads the X register with zero. In practice, this marks the start of a loop, like a FOR loop at character 0 “H” in ‘Hello World!’
Line 60:.loop – marks the start of the loop we will use to cycle through the ‘Hello World!’ string we defines from line 36.
Line 70: Loads the accumulator by referencing the helloworld function at line 34. The X reference is keeping tack of where we are in the loop as we’re displaying the characters one by one (starting at 0 as mentioned in line 50).
Line 80: JSR stands for ‘Jump to SubRoutine’ and is used to jump to an in-built machine code routine to OSWRCH (Operating System Write Character). This is used, as you might imagine, to write characters to the screen and is found on the BBC Micro at &FFEE.
Line 90: INX is ‘Increment X register’ and increments this by one on each pass. This is part of our loop which is printing each of the characters in the string .
Line 100: CMP stands for ‘Compare’ and we are comparing the character we are on in the string with that here. ‘&D’ is decimal 13 and equates to the CR we mentioned in line 38. Since this is the last ASCII ‘character’ to be printed we know that if this is found, the full string has now been displayed.
Line 110: BNE stands for Branch if Not Equal and will continue the loop if &D hasn’t been found, above.
Line 115: Reset the X register back to 0. We need to do this as we will be re-running the whole code again in an endless loop and need to reset to the start of the string.
Line 116: Jump back into the loop. This is effectively ‘GOTO 10’ in the above BASIC version.
Line 120:Return From Subroutine (RTS) because &D has been found by the Compare above and we’re happy that the string we’ve printed is now complete. In practice, this is never reached as we are in a continuous loop but this is where it should go! If we were to remove lines 115 and 116 the program would complete here (and ‘Hello World!’ would be displayed once and finish).
Line 140: Finally we use the BASIC command CALL to execute the machine code routine to print the message.
That’s it…relatively straightforward although the BASIC equivalent is obviously somewhat easier to understand! I will hopefully do something a little more interesting next time, maybe draw a square on the screen or something. Let’s see.
The rumours about Microsoft’s enforcement of the Black Lotus boot kit mitigations have been around since May 2023 but so far Microsoft have (sensibly) held back enforcement. And with good reason – the mitigations, once applied, are known to cause all sorts of problems with booting, PXE boot, USB boot, CD, even SecureBoot. As you can imagine, this could become a support headache, especially when applied at enterprise level customers.
I have recently had the dubious pleasure of investigating this and assessing what impact this might have when it’s forcibly imposed in some future KB (incidentally, no concrete date set from what I have heard so far, but possibly Q1 2025* although this date keeps getting shunted forward).
* This will be June 2026
In any case, I thought I’d share the benefit of my knowledge for those struggling to get stuff working, particularly PXE booting via WDS. In all likelihood, any machines you’re preparing for have already got the ‘payload’ in place – that is, it’s already present on your machines but just needs activation. Thankfully the Microsoft process for update has been significantly improved over the last year and, following the November KBs, the certificates can be updated in approx two reboots and via GPO (assuming FW is up to date, etc – there can still be dead ends here if not).
Once the mitigations have been applied, there shouldn’t be any immediately noticeable issues with the machine, although there are reports by some of being unable to boot into the OS. If this happens, you may wish to temporarily disable SecureBoot and follow guidance from MSFT. However I wouldn’t expect this to happen and I haven’t personally come across it yet.
However, you will start to notice problems when you attempt to PXE boot or boot off some other media. The reason for this is that the certificates in the UEFI BIOS have now been updated to 2023 from 2011 and fail the integrity check when booting using binaries with unmatched certs. There are three areas we have to update:
The Boot Image
The WDS/Native SCCM PXE Binaries
The OS Media
Boot Image
This should be the first port of call. When creating the image, make sure you have installed the ADK 10.1.26100.1 (May 2024) and in particular, the WinPE Add-On. This version contains all the latest certificates within the winpe.wim file and will ensure compatibility/bootability(!).
Windows Deployment Server
Ensure the server has a recent (at least June 2024) KB update. This will ensure it has a copy of the binaries required to PXEboot containing the new certs available.
Strictly speaking, the mui’s aren’t necessary but…belt and braces. What we’re doing here is replacing the old binaries with the new 2023 binaries which were supplied in the latest KB. If you have more than one WDS server, obviously ensure all are updated appropriately. In our environment, we also had one or two hard-coded boot paths which caused further confusion but I wouldn’t expect that normally.
PXE via Native SCCM
If you use the native PXE responder in SCCM rather than WDS, follow the steps below:
Browse to <MOUNTPOINT>\sources and copy boot.wim to a new folder (D:\Updates).
Mount the boot image, eg Dism /mount-wim /wimfile:D:\Updates\boot.wim /index:1 /mountdir:D:\Updates\MOUNT
Copy the following files to your update directory: D:\Updates\MOUNT\Windows\Boot\EFI_EX\bootmgfw_EX.efi D:\Updates\MOUNT\Windows\Boot\PXE_EX\wdsmgfw_EX.efi
Rename bootmgfw_EX.efi to bootmgfw.efi and wdsmgfw_EX.efi to wdsmgfw.efi
Copy the renamed files to D:\SMS_DP$\sms\bin\SMSBoot\<PkgID\>\x64 on your PXE server (substitute for C: if necessary)
You should be able to boot an updated machine now.
NOTE:wdsmgfw_EX.efi and bootmgfw_EX.efi can also be found on the boot image in the May 24 ADK. I had no luck trying the get the versions included there working correctly even though the certificates stated 2023, so it’s recommended you stick with the versions in the latest 24H2 ISO.
OS Media (Task Sequence)
So….we should now be working, right? Not so fast. You should now be in a position to be able to boot from WDS. However, if your OS media is out of date you will also be in trouble. If this is the case, you’ll find your task sequence failing once the OS has been laid down with bcdboot.exe failing to find the appropriate files it needs. From an OS media perspective you will need a minimum of the following:
If you ensure these or later versions are part of your task sequence, everything should be rosy.
OS Media (ISO Image)
Sometimes we need an ISO image to boot off. The instructions below should help when updating an ISO with the mitigations:
On SCCM – Upgrade to latest ADK and create a bootable ISO
Pre-Requisites On client machine ( eg win 11 ) Install Windows latest ADK (ADK 10.1.26100.1 (May 2024)) on your system, ensuring you include Deployment Tools. Obtain the most recent Windows 11 23H2/24H2 installation media through your preferred distribution channel, such as the Volume Licensing portal. This latest installation media contains the UEFI 2023 CA signed boot managers within the boot.wim file.
Once you have installed ADK, open Deployment and Imaging Tools Environment with administrative privileges. Create the following directories: mkdir C:\UpdateWinMedia\DVD mkdir C:\UpdateWinMedia\Boot mkdir C:\UpdateWinMedia\Mount
Mount the Windows installation ISO media on your system. In this example, the drive letter is F:
Copy the contents of the Windows installation media (F:) to C:\UpdateWinMedia\DVD xcopy /s /h F:\ C:\UpdateWinMedia\DVD
Mount the Boot.wim file to extract updated boot files Dism /mount-wim /wimfile:C:\UpdateWinMedia\DVD\sources\boot.wim /index:1 /mountdir:C:\UpdateWinMedia\Mount
Create bootable DVD using oscdimg tool with the UEFI 2023 CA signed efisys.bin oscdimg -m -o -u2 -udfver102 -pEF -b”C:\UpdateWinMedia\Boot\DVD_EX\EFI\en-US\efisys_EX.bin” C:\UpdateWinMedia\DVD C:\UpdateWinMedia\Windows11_UEFI2023.iso
Boot using the updated ISO and install Windows 11.
Hope the above is useful to someone, certainly cost me a good few hours of my life!
Headaches of an SCCM Admin.
Manage Cookie Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behaviour or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.