5 нояб. 2013 г.

Работа с образами Windows. Часть 2: загрузка WinPE через PXE.

Предыдущие части статьи:
Работа с образами Windows. Часть 1. Собираем Windows PE.
В предыдущей части мы собирали образ WinPE с добавлением нужных пакетов и драйверов. Напомню, что с точки зрения Microsoft, правильным способом массового развертывания Windows является Windows Deployment Services, но мы делаем простое и удобное решение для небольших организаций.

Для загрузки по сети будем использовать штатный для FreeBSD и большинства дистрибутивов Linux сервер DHCP - ISC DHCP, сервер TFTP и загрузчик pxelinux. Конечно, ничто не мешает использовать DHCP и TFTP серверы из Windows, а WinPE грузить напрямую, без дополнительных загрузчиков.
Начнем с подготовки WinPE для загрузки по сети. Нам нужно будет подготовить файл данных конфигурации загрузки (BCD) и неплохо бы добавить в автозапуск скрипт для вывода меню со списком ОС для развертывания. Скрипт для запуска меню удобнее всего запускать, добавив строчку в штатный startnet.cmd:
wpeinit
call menu1.cmd
Вот и само меню (menu1.cmd). Для публикации я его несколько сократил, сделав его одноуровневым (уж очень большой у нас список дистрибутивов для развертывания), но смысл будет понятен: монтируем SMB ресурс, на котором лежат образы и скрипты развертывания (работа которых будет описана позже, мы еще даже захват образов не изучали), выводим меню со списком ОС и ждем ввода от пользователя:
@echo off
set target_disk=0
Set nw_share=\\192.168.0.200\share_name
Set nw_share_user=DOMAIN_NAME\user_name
Set nw_share_pwd=password

::___________________________________________________________________
:_menu
cls
echo Main menu
echo Target disk is %target_disk%
echo Select task:
echo.
echo 1] List disks
echo 2] List volumes
echo 3] Apply Win Srv 2008 R2 Ent Eval to disk %target_disk%
echo 4] Apply Win Srv 2008 R2 Ent RUS Corporate to disk %target_disk%
echo 5] Apply Win Srv 2012 Std Eval to disk %target_disk%
echo 6] Reboot
echo 7] Shutdown
echo 8] Exit

set choice=
set /p choice=Type option [1 to 8] and press ENTER :
if '%choice%'=='1' goto dp_list_disk
if '%choice%'=='2' goto dp_list_volumes
if '%choice%'=='3' goto nw_deploy_1_1
if '%choice%'=='4' goto nw_deploy_1_2
if '%choice%'=='5' goto nw_deploy_2
if '%choice%'=='6' wpeutil reboot
if '%choice%'=='7' wpeutil shutdown
if '%choice%'=='8' goto _end
goto _menu

::___________________________________________________________________
:dp_list_disk
diskpart /s listdisk.txt
pause
goto _menu

::___________________________________________________________________
:dp_list_volumes
diskpart /s listvolumes.txt
pause
goto _menu

::___________________________________________________________________
:nw_deploy_1_1
net use y: %nw_share% %nw_share_pwd% /user:%nw_share_user%
y:
call deploy.cmd winsrv2008r2.wim 1
pause
goto _menu

::___________________________________________________________________
:nw_deploy_1_2
net use y: %nw_share% %nw_share_pwd% /user:%nw_share_user%
y:
call deploy.cmd winsrv2008r2.wim 2
pause
goto _menu

::___________________________________________________________________
:nw_deploy_2
net use y: %nw_share% %nw_share_pwd% /user:%nw_share_user%
y:
call deploy.cmd winsrv2012.wim 1
pause
goto _menu

::___________________________________________________________________
:_end
cls
ECHO.
ECHO ENDING SCRIPT...
echo.
echo.
echo.
pause
endlocal
Файлы listdisk.txt и listvolumes.txt - это простые скрипты для diskpart, выводящие список физических дисков и список томов соответственно:
list disk
exit
list vol
exit
Вот скрипт для генерации сетевого дистрибутива WinPE:
@echo off

REM где хранить PXE-дистрибутив
Set pxe_root=G:\opk\pxe

REM где лежит собранный WinPE
Set winpe_root=G:\opk\winpe_build

REM путь установки ADK
Set adk_path=%programfiles(x86)%\Windows Kits\8.1\Assessment and Deployment Kit

REM путь к дополнительным скриптам для интеграции в WinPE
Set scripts_path=G:\opk\winpe\scripts

REM вызов скрипта из состава ADK для установки переменных
call "%adk_path%\Deployment Tools\DandISetEnv.bat"

REM очистка каталога с PXE-дистрибутивом
if exist %pxe_root% rd /q /s %pxe_root%

REM создаем каталоги для PXE-дистрибутива
mkdir %pxe_root%
mkdir %pxe_root%\Boot

REM копируем wim образ, монтируем его, копируем нужные файлы из него
copy %winpe_root%\media\sources\boot.wim %pxe_root%\Boot\winpe.wim
Dism /Mount-Wim /WimFile:%pxe_root%\Boot\winpe.wim /index:1 /MountDir:%winpe_root%\mount
copy %winpe_root%\mount\Windows\Boot\PXE\*.* %pxe_root%\Boot\
copy %winpe_root%\media\boot\boot.sdi %pxe_root%\Boot\boot.sdi
copy %winpe_root%\mount\Windows\System32\bcdedit.exe %pxe_root%\Boot\bcdedit.exe

REM помещаем скрипты
copy /Y %scripts_path%\*.* %winpe_root%\mount\Windows\System32\

REM размонтируем образ
Dism /Unmount-Wim /MountDir:%winpe_root%\mount\ /Commit

REM генерация загрузчика
%pxe_root%\Boot\bcdedit.exe -createstore %pxe_root%\Boot\BCD
set BCDEDIT=%pxe_root%\Boot\bcdedit.exe -store %pxe_root%\Boot\BCD
%BCDEDIT% -create {ramdiskoptions} /d "Ramdisk options" 
%BCDEDIT% -set {ramdiskoptions} ramdisksdidevice boot
%BCDEDIT% -set {ramdiskoptions} ramdisksdipath \Boot\boot.sdi

REM ищем GUID
for /f "tokens=3 delims={} " %%a in ('%BCDEDIT% -create -d "Windows PE" -application osloader') do set guid=%%a

REM прописываем winpe в меню загрузки
%BCDEDIT% -set {%guid%} systemroot \Windows
%BCDEDIT% -set {%guid%} detecthal Yes
%BCDEDIT% -set {%guid%} winpe Yes
%BCDEDIT% -set {%guid%} osdevice ramdisk=[boot]\Boot\winpe.wim,{ramdiskoptions}
%BCDEDIT% -set {%guid%} device ramdisk=[boot]\Boot\winpe.wim,{ramdiskoptions}
%BCDEDIT% -create {bootmgr} /d "Windows BootManager"
%BCDEDIT% -set {bootmgr} timeout 30 
%BCDEDIT% -displayorder {%guid%}

REM удаляем ненужный bcdedit
del /Q %pxe_root%\Boot\bcdedit.exe
Мы уже можем грузить WinPE при помощи файла pxeboot.n12, но будет удобнее делать это через дополнительный загрузчик. Ведь помимо развертывания Windows есть и масса других задач, например запуск memtest86 и прошивка материнских плат и контроллеров из DOS.
Следующий этап - конфигурация Pxelinux. Pxelinux является частью проекта Syslinux и последнюю версию можно найти на kernel.org. Syslinux и Pxelinux хорошо задокументированы в собственной Вики. Из дистрибутива Syslinux нужны будут следующие файлы: chain.c32, ldlinux.c32, libcom32.c32, libutil.c32, memdisk, pxelinux.0, vesamenu.c32. Грузить нужно файл pxelinux.0, т.е. в dhcpd.conf указываем:
next-server ;
filename "/tftpboot/pxelinux.0";
В tftpd.rules нужно добавить rg \\ / для правильной работы со прямыми и обратными слэшами в путях.
Конфигурация pxelinux (файл pxelinux.cfg/default с vesa-меню, обоями, запуском двух версий memtest86 и примерами загрузки образов дисков с DOS и прошивками для материнских плат:
    DEFAULT vesamenu.c32
    ALLOWOPTIONS 0
    PROMPT 0
    FONT cp866-8x16.psf
    TIMEOUT 300
    ONTIMEOUT local
     
    MENU TITLE PXE boot menu
#splash.png - картинка с темным фоном в 640x480
    MENU BACKGROUND splash.png

#цвета для рамки и пунктов меню
    MENU COLOR border 30;44 #00000000 #00000000 none
    MENU COLOR unsel 37;44 #90ffffff #00000000 std
    MENU COLOR sel 7;37;40 #70ffffff #20ff8000 all
    MENU COLOR hotsel 1;7;37;40 #e0ffffff #20ff8000 all

#первое меню - загрузка WinPE
    MENU BEGIN winpe
    MENU TITLE Microsoft Windows Setup
     
            LABEL MAINMENU
            MENU LABEL ^back
            MENU EXIT
     
            LABEL winpe
            MENU LABEL WinPE
            kernel /Boot/pxeboot.0
   
    MENU END
#второе меню - тесты
    MENU BEGIN tests
    MENU TITLE Tests
     
            LABEL MAINMENU
            MENU LABEL ^back
            MENU EXIT
     
            LABEL memtestplus
            MENU LABEL Memtest86+ 4.20
            kernel /fd/memtpl
   
   LABEL memtest
            MENU LABEL Memtest86 4.0
            kernel /fd/memtest
   
    MENU END
#меню с прошивками для плат. Через memdisk загружаются сжатые 8-16МБ образы HDD с DOS и необходимыми для прошивки файлами.
MENU BEGIN smc_bios
    MENU TITLE Supermicro BIOS Updates
 LABEL MAINMENU
        MENU LABEL ^back
        MENU EXIT
   
  MENU BEGIN x8d
  MENU TITLE X8Dxx
  
            LABEL MAINMENU
            MENU LABEL ^back
            MENU EXIT
       
     LABEL x8da3
            MENU LABEL X8DA3, X8DAi(-F) v 2.1a
            LINUX memdisk
     INITRD /fd/sm/x8d/x8da3.img.gz
   
     LABEL x8da6
            MENU LABEL X8DA6, X8DAE(-F) v 2.0c
            LINUX memdisk
     INITRD /fd/sm/x8d/x8da6.img.gz
  
     MENU END
 MENU END
 
#загрузка с HDD 
    LABEL local
    MENU LABEL Boot from HDD
    #LOCALBOOT 0
    KERNEL chain.c32
    APPEND hd0 0
Копируем все в корень tftp сервера, включая каталог Boot с сетевым дистрибутивом WinPE. Если все сделали правильно, то при загрузке через PXE мы должны увидеть меню Pxelinux:
При выборе загрузки WinPE мы должны увидеть его загрузку и запуск:
При возникновении проблем на этом этапе возможно потребуется скопировать файл Boot\pxeboot.n12 в Boot\pxeboot.0.
Подготовить образы HDD с DOS для вышеупомянутой прошивки контроллеров и платы проще простого. Создается пустой образ достаточного размера (например, 32МБ, чтобы влезли большие BIOSы для последних плат Supermicro X9): dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*32]. Делать несколько заготовок с меньшим размером смысла нет, так как будем грузить сжатые gzip'ом образы. Далее ставим туда DOS (MS-DOS 6.22 или 7, с FreeDOS с некоторыми прошивальщиками возможны проблемы). После этого готовим в Linux множество отдельных образов под каждую прошивку: копируем образ с чистым DOS и монтируем, копируем файлы, отмонтируем, сжимаем gzip'ом.