I'm trying to install a windows PE on a partition on same HDD with windows.
I copied winPE files ADK with Deployment Tools and Imaging Environment:
copype amd64 C:\WinPE_amd64
I used this code to make partitions:
diskpart
list disk
select <disk number>
clean
rem === Create the Windows PE partition. ===
create partition primary size=2000
format quick fs=fat32 label="Windows PE"
assign letter=P
active
rem === Create a data partition. ===
create partition primary
format fs=ntfs quick label="Other files"
assign letter=O
list vol
exit
I applied image on partition P: with command: dism /Apply-Image /ImageFile:"C:\WinPE_amd64\media\sources\boot.wim" /Index:1 /ApplyDir:P:\
I set up boot files with command BCDboot P:\Windows /s P: /f ALL, but after reboot i can't see WinPE in boot menu or in bcdedit.
I set up a lot of multi-boot machines - usually with some flavor of windows and winPE. I make a system volume and register the bootable OSes onto that. I think the recommendation is to do that - even if you're not interested in dual boot.
The script will be different depending on whether your firmware is UEFI or good ol' BIOS - Some of the tools seem to like a GPT better. BCDBoot, as I remember it, was fairly persnickety.
The system volume has to be FAT32, but your winPE should probably be NTFS. Here's a script similar to what I run when forced to stick with BIOS/MBR:
select disk {0}
clean
create partition primary size={1}
format quick fs=ntfs label="System Reserved"
assign letter="{2}"
active
create partition primary size={3}
format quick fs=ntfs label="{4}"
assign letter="{5}"
create partition primary
format quick fs=ntfs label="WinPE"
assign letter="{6}"
exit
Note that in the foregoing, the system volume is the active volume.
If you're on a UEFI machine and/or a system that supports GPT, you'd do it more like this:
select disk {0}
clean
convert gpt
create partition efi size={1}
format quick fs=fat32 label="System"
assign letter="{2}"
create partition msr size={3}
create partition primary size={4}
format quick fs=ntfs label="{5}"
assign letter="{6}"
create partition primary
format quick fs=ntfs label="WinPE"
assign letter="{7}"
exit
There's no "active" command on an EFI-booted drive - the EFI volume is always the active volume.
You'd make the choice of which to run based on the firmware you want to run under - found in your BIOS configuration menu (F12 at startup - but I guess that is hardware vendor-specific).
In either case, You'd still register the OSes in the bcd with bcdboot. You don't typically have to specify the /s switch with EFI. Also, you don't have to specify all firmware types - it will default based on the active firmware - no point in having more stuff in the bcd than you really need - it's arcane and worth keeping simple/small.
I tend to use the /addlast switch when registering winPE using BCDBoot- as we only boot to it in special circumstances (in my world). I also remove it from the displayOrder - so users don't inadvertently boot to it when it isn't appropriate.
If this is a secondary drive you're putting this on - you have to set the boot order in BIOS to make your secondary drive show up.
Alternatively, you might be able to register a bootable partition in the primary disk's BCD...in which case, you'd either need to sniff out the primary drive's active partition, temporarily assign it a drive letter, and register to that (or don't use the /s switch at all). I've never had the occasion to put a bootable partition from a secondary disk into the primary's BCD - but I suppose it could work.
Related
I wrote a firmware to run our ESP32-based custom PCB.
The firmware holds a unique S/N (serial number) in the NVS thru Preferences API which is set thru the bluetooth app I wrote.
But now I have to produce tens of PCB and it takes time to connect and set the S/N thru the app.
The current process is a 2-step process which I want to streamline:
flash the generic firmware
set the unique S/N
I am wondering if I could write a script that could do both steps, providing the S/N as the script argument.
I could take advantage of Espressif esp tool write_flash for example.
How could I do that?
You can pre-generate the NVS data partition and flash it together with firmware. ESP IDF provides the NVS Partition Generator Utility specifically for for that purpose. Here's an overview of the process.
First you create a CSV file (let's name it mfgdata.csv) with your pre-generated data, e.g. serial number, product ID, keypair, whatever. Assume the NVS namespace is "mfgdata_ns".
key,type,encoding,value
mfgdata_ns,namespace,,
serial,data,string,"ABC1234"
private_key,file,string,/path/key.pri
Then you generate the binary partition with NVS data on it (named mfgdata.bin) from this CSV file. Assume the NVS partition starts at address 0x3000.
$IDF_PATH/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py generate mfgdata.csv mfgdata.bin 0x3000
Finally you flash the NVS partition together with your firmware. Here's a sample flashing command for the NVS partition alone (assuming the partition is named "mfgdata_part" in your partition table).
$ $IDF_PATH/components/partition_table/parttool.py -p /dev/ttyUSB0 -b 921600 write_partition --partition-name=mfgdata_part --input=mfgdata.bin
Firmware starts up, loads the NVS namespace and finds all values that you specified in mfgdata.csv.
You have to be careful when creating the CSV file. Some 2 years ago they were using the python CSV module to parse this file and it worked perfectly, as expected. Then some not very bright person decided to ditch the python module and replace it by splitting each line on comma character, silently ignoring all parsing problems. I don't know if they've unf*cked it yet.
I think FS stands for filesystem, but I don't know what BLK stands for. Not only that, but what are the meanings behind the pci hierarchy parameters. i.e. When I see HD(1,MBR,0x0003B) what does "1","MBR", and what looks to be an address, stand for?
Here's the mapping table I'm looking at in UEFI shell:
Mapping table
FS0: Alias(s):HD21a0e0b:;BLK1:
PciRoot(0x0)/Pci(0x1D,0x0)/USB(0x0,0x0)/USB(0x4,0x0)/HD(1,MBR,0x0003B)
FS1: Alias(s):HD23a0a1:;BLK4:
PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x0,0x0)/HD(1,MBR,0x00000000,0x3F)
BLK3: Alias(s):
PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x0,0x0)
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x1D,0x0)/USB(0x0,0x0)/USB(0x4,0x0)
BLK2: Alias(s):
PciRoot(0x0)/Pci(0x1D,0x0)/USB(0x0,0x0)/USB(0x4,0x0)/HD(2,MBR,0x0003B)
I'm guessing BLK's are available ports and FS's are physical things that are plugged into those ports. It looks like once somethign is plugged into a BLK, it becomes an FS, but still retains its BLK value. i.g. FS0=BLK1
According to archwiki:
fsX means filesystem
blkX means block device or data storage device
MBR should mean Master Boot Record
HD should mean Hard Drive
1 might mean Primary, 2 Secondary Partition
That hex number after MBR could be the device signature or disk identifier. Or maybe an offset of that device to important information.
Links that might help further:
RHEL 5 Installation Guide EFI Shell Guide
Red Hat 7.1 Itanium EFI Shell Guide
HP Knowledge Base: "UEFI Shell 'fs' devices gone after restore from image backup"
OpenVMS: Firmware upgrades from a USB stick (on UEFI)
SourceForge EFI Shell Development Documentation
How to uniquely identify computer (mainboard) using C#(.Net/Mono, local application)?
Edition. We can identify mainboard in .Net using something like this (see Get Unique System Identifiers in C#):
using System.Management;
...
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_MotherboardDevice");
...
But unfortunately Mono does not support System.Management. How to do it under Mono for Linux? - I don't know :(
Write a function that takes a few unique hardware parameters as input and generates a hash out of them.
For example, Windows activation looks at the following hardware characteristics:
Display Adapter
SCSI Adapter
IDE Adapter (effectively the motherboard)
Network Adapter (NIC) and its MAC Address
RAM Amount Range (i.e., 0-64mb, 64-128mb, etc.)
Processor Type
Processor Serial Number
Hard Drive Device
Hard Drive Volume Serial Number (VSN)
CD-ROM / CD-RW / DVD-ROM
You can pick up a few of them to generate your unique computer identifier.
Please see: Get Unique System Identifiers in C#
You realistically have MotherboardID, CPUID, Disk Serial and MAC address, from experience none of them are 100%.
Our stats show
Disk serial Is missing 0.1 %
MAC Is missing 1.3 %
Motherboard ID Is missing 30 %
CPUID Is missing 99 %
0.04% of machines tested yielded no information, we couldn't even read the computer name. It maybe that these were some kind of virtual PC, HyperV or VMWare instance, or maybe just very locked down? In any case your design has to be able to cope with these cases.
Disk serial is the most reliable, but easy to change, mac can be changed and depending on the filtering applied when reading it can change if device drivers are added (hyperv, wireshark etc).
Motherboard and CPUID sometimes return values that are invalid "NONE", "AAAA..", "XXXX..." etc.
You should also note that these functions can be very slow to call (they may take a few seconds even on a fast PC), so it may be worth kicking them off on a background thread as early as possible, you ideally don't want to be blocking on them.
Try this:
http://carso-owen.blogspot.com/2007/02/how-to-get-my-motherboard-serial-number.html
Personally though, I'd go with hard drive serial number. If a mainboard dies and is replaced, that PC isn't valid any more. If the HDD drive is replaced, it doesn't matter too much because the software was on it.
Of course, on the other hand, if the HDD is just moved elsewhere, the information goes with it, so you might want to look at a combination of serial numbers, depending what you want it for.
How about the MAC address of the network card?
I'm trying to write a test pattern to every sector of a formatted USB drive. There is one logical drive (e.g. h:). This volume is FAT-formatted and contains data to be overwritten. Also, I want to overwrite the whole physical drive. The program is running with elevated user rights.
First I did the following:
// from the drive letter "h:" I get the physical disk number using
// IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS => "\\.\PhysicalDrive2"
hDevice = ::CreateFile( "\\.\PhysicalDrive2", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
// get the number of available sectors with IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
// => ulNumberOfSectors
// now I try to write some sectors, e.g. 2 (I want to use a higher value):
WriteFile( hDevice, abBuffer, 2*512, &byteswritten, NULL );
The call to WriteFile fails with ERROR_ACCESS_DENIED.
If I write one sector, it works.
When I overwrite the first sector and plug the device out and in again, Windows wants to format it. In this situation my code with 2048 sectors at once works without ERROR_ACCESS_DENIED.
I also unmounted the volume as described in CodeProject: WriteFile on Physical Drives with Windows 7 but this didn't change anything. Obviously the volume is unmounted because it's no longer visible in Windows Explorer.
I want to write more than a single sector due to perfomance reasons. I'm also afraid that other problems in the field might occur because I don't fully understand ths problem.
Any suggestions?
I didn't have problems with different WriteFile() sizes, but I did solve the
WriteFile(): Access is denied <ERROR_ACCESS_DENIED/5> to
'\.\physicaldriveX
devices (usually USB HDD/SSD) in Windows 7 running as Administrator (elevated rights) as follows:
Computer Management -> Disk Management:
Volume (H: in your case) -> right-click -> Delete Volume
Disk (Disk 2 in your case) -> right-click -> Off-line
Disk (Disk 2 in your case) -> right-click -> On-line
After that, I'm able to write to '\.\physicaldriveX' with no problem.
I think the Win7 locks (unlike previous Windows releases) the physical device as long as there is any file system on the device to avoid consistency problems.
You cannot directly access sectors of a drive which are owned by a mounted filesystem.
See Changes to the file system and to the storage stack to restrict direct disk access and direct volume access
The documentation for FSCTL_DISMOUNT_VOLUME describes the following sequence for overwriting a filesystem:
Open a volume.
Lock the volume.
Format the volume.
Dismount the volume.
Unlock the volume.
Close the volume handle.
Your pattern-writing operation would be in step 3 instead of formatting.
Another method is to use clean to delete all the partitions (and ALL DATA) on the disk:
C:\> diskpart
Diskpart> list disk
Diskpart> select disk N (where N is your disk number)
Diskpart> clean
Diskpart> exit
I'm trying to figure out the available disk space programmatically in windows. For this, I need to first get a list of the available drives, then check which of those are local drives and then query the available bytes on each local drive.
I'm a bit stuck on the first part, where the API presents two functions:
GetLogicalDrives (http://msdn.microsoft.com/en-us/library/aa364972(VS.85).aspx) which gives you a DWORD with the bits set (bit 0 if drive A is present, bit 1 if drive B etc)
GetLogicalDriveStrings (http://msdn.microsoft.com/en-us/library/aa364975(VS.85).aspx) which gives you the actual strings.
Now, although I'll be using strings later on, I'd prefer using the first option for querying. However, on my system a DWORD is typedef-ed to "unsigned long", which is 4 bytes, whereas drive letters only range A-Z (26 - i think - characters). Obviously, one can define more than 26 drives on their system (however unlikely they are to do so) - so I was wondering if there was any convention for those drives. Can someone point me to a resource on this?
Thanks.
DWORD is always 4 bytes, regardless of the system (it's a Win32 type).
The maximum for drive letters in Windows is 26. Because English alphabet has only 26 letters :). However, Windows allows two ways to mount a volume:
to a drive letter
to a directory (on an NTFS volume).
You can mount one volume to multiple locations (but no more than one drive letter, IIRC). A GUI for this task is presented by Control Panel -> Administrative Tools -> Computer Management -> Disk Management.
If you want to have more than 26 drives with the additional drives being redirects to already active drives and are okay with them not working properly in most programs, then you can assign more with the following method (be warned they won't even show up in the file explorer):
subst ♪: C:\Temp\
cd /D ♪:\
and to delete them (also they aren't preserved through restarts):
subst /D ♪:
You can enumerate all volumes and their mount points as described in this article.
You could use WMI. The following WMI query should list all drives:
SELECT * FROM Win32_DiskDrive
It it not sufficient to enumerate MS-DOS drives (there can be at most 26 of them, by the way, although each can be bound twice, once globally and once locally in your session), a volume can, for example, be mounted to a directory. What you want is probably to enumerate all volumes in the system, using FindFirstVolume et al. Take a look at the associated MSDN example.