installable hooks
This patch "sets the stage" for the memdisk kernel to include
different
"installables": versions of the memdisk hooks.
This patch splits the case of the EDD-compiled hook from the non-EDD-compiled
hook. Both are available inside the kernel, and the kernel chooses which one
to install based on the command-line.
It''s possible that other, slightly modified versions of the memdisk
hook could
be useful to have...
---
memdisk/Makefile | 9 +-
memdisk/memdisk.asm | 988 +----------------------------------------------
memdisk/memdisk.inc | 987 ++++++++++++++++++++++++++++++++++++++++++++++
memdisk/memdisk_edd.asm | 2 +
memdisk/setup.c | 28 +-
5 files changed, 1014 insertions(+), 1000 deletions(-)
create mode 100644 memdisk/memdisk.inc
create mode 100644 memdisk/memdisk_edd.asm
diff --git a/memdisk/Makefile b/memdisk/Makefile
index 3776731..b8cb91a 100644
--- a/memdisk/Makefile
+++ b/memdisk/Makefile
@@ -20,7 +20,7 @@ LDFLAGS =3D $(GCCOPT) -g
INCLUDE =3D -I$(topdir)/com32/include
NASM =3D nasm
NASMOPT =3D -O9999
-NFLAGS =3D -dDATE=3D''"$(DATE)"'' -dWITH_EDD
+NFLAGS =3D -dDATE=3D''"$(DATE)"''
NINCLUDE =3D
=20
SRCS =3D $(wildcard *.asm *.c *.h)
@@ -38,11 +38,11 @@ endif
# Important: init.o16 must be first!!
OBJS16 =3D init.o16 init32.o
OBJS32 =3D start32.o setup.o msetup.o e820func.o conio.o memcpy.o memset.o \
- unzip.o memdisk.o
+ unzip.o memdisk.o memdisk_edd.o
=20
CSRC =3D setup.c msetup.c e820func.c conio.c unzip.c
SSRC =3D start32.S memcpy.S memset.S
-NASMSRC =3D memdisk.asm memdisk16.asm
+NASMSRC =3D memdisk.asm memdisk_edd.asm memdisk16.asm
=20
all: memdisk # e820test
=20
@@ -110,6 +110,9 @@ e820test: e820test.c e820func.c msetup.c
memdisk.o: memdisk.bin
$(LD) -r -b binary -o $@ $<
=20
+memdisk_edd.o: memdisk_edd.bin
+ $(LD) -r -b binary -o $@ $<
+
.depend:
rm -f .depend
for csrc in *.c ; do $(CC) $(INCLUDE) $(CFLAGS) -MM $$csrc >> .depend ;
done
diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm
index 0d48961..daa5c0a 100644
--- a/memdisk/memdisk.asm
+++ b/memdisk/memdisk.asm
@@ -1,987 +1 @@
-; -*- fundamental -*- (asm-mode sucks)
-; ****************************************************************************
-;
-; memdisk.asm
-;
-; A program to emulate an INT 13h disk BIOS from a "disk" in
extended
-; memory.
-;
-; Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
-;
-; This program is free software; you can redistribute it and/or modify
-; it under the terms of the GNU General Public License as published by
-; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-; Boston MA 02111-1307, USA; either version 2 of the License, or
-; (at your option) any later version; incorporated herein by reference.
-;
-; ****************************************************************************
-
-%ifndef DEPEND
-%include "../version.gen"
-%endif
-
-; %define DEBUG_TRACERS ; Uncomment to get debugging tracers
-
-%ifdef WITH_EDD
-%define EDD 1
-%else
-%define EDD 0
-%endif
-
-%ifdef DEBUG_TRACERS
-
-%macro TRACER 1
- call debug_tracer
- db %1
-%endmacro
-
-%else ; DEBUG_TRACERS
-
-%macro TRACER 1
-%endmacro
-
-%endif ; DEBUG_TRACERS
-
-%define CONFIG_READONLY 0x01
-%define CONFIG_RAW 0x02
-%define CONFIG_SAFEINT 0x04
-%define CONFIG_BIGRAW 0x08 ; MUST be 8!
-
- org 0h
-
-%define SECTORSIZE_LG2 9 ; log2(sector size)
-%define SECTORSIZE (1 << SECTORSIZE_LG2)
-
- ; Parameter registers definition; this is the definition
- ; of the stack frame.
-%define P_DS word [bp+34]
-%define P_ES word [bp+32]
-%define P_EAX dword [bp+28]
-%define P_HAX word [bp+30]
-%define P_AX word [bp+28]
-%define P_AL byte [bp+28]
-%define P_AH byte [bp+29]
-%define P_ECX dword [bp+24]
-%define P_HCX word [bp+26]
-%define P_CX word [bp+24]
-%define P_CL byte [bp+24]
-%define P_CH byte [bp+25]
-%define P_EDX dword [bp+20]
-%define P_HDX word [bp+22]
-%define P_DX word [bp+20]
-%define P_DL byte [bp+20]
-%define P_DH byte [bp+21]
-%define P_EBX dword [bp+16]
-%define P_HBX word [bp+18]
-%define P_HBXL byte [bp+18]
-%define P_BX word [bp+16]
-%define P_BL byte [bp+16]
-%define P_BH byte [bp+17]
-%define P_EBP dword [bp+8]
-%define P_BP word [bp+8]
-%define P_ESI dword [bp+4]
-%define P_SI word [bp+4]
-%define P_EDI dword [bp]
-%define P_DI word [bp]
-
- section .text
- ; These pointers are used by the installer and
- ; must be first in the binary
-Pointers: dw Int13Start
- dw Int15Start
- dw PatchArea
- dw TotalSize
- dw IretPtr
-
-IretPtr equ Int13Start.iret
-Int13Start:
- ; Swap stack
- mov [cs:Stack],esp
- mov [cs:SavedAX],ax
- mov ax,ss
- mov [cs:Stack+4],ax
- mov ax,cs
- mov ss,ax
- mov sp,[cs:MyStack]
-
- ; See if DL points to our class of device (FD, HD)
- push dx
- push dx
- xor dl,[cs:DriveNo]
- pop dx
- js .nomatch ; If SF=3D0, we have a class match here
- jz .our_drive ; If ZF=3D1, we have an exact match
- cmp dl,[cs:DriveNo]
- jb .nomatch ; Drive < Our drive
- dec dl ; Drive > Our drive, adjust drive #
-.nomatch:
- mov ax,[cs:SavedAX]
- pushf
- call far [cs:OldInt13]
- pushf
- push bp
- mov bp,sp
- cmp byte [cs:SavedAX+1],08h
- je .norestoredl
- cmp byte [cs:SavedAX+1],15h
- jne .restoredl
- test byte [bp+4],80h ; Hard disk?
- jnz .norestoredl
-.restoredl:
- mov dl,[bp+4]
-.norestoredl:
- push ax
- push ebx
- push ds
- mov ax,[bp+2] ; Flags
- lds ebx,[cs:Stack]
- mov [bx+4],al ; Arithmetric flags
- pop ds
- pop ebx
- pop ax
- pop bp
- lss esp,[cs:Stack]
-.iret: iret
-
-.our_drive:
- ; Set up standard entry frame
- push ds
- push es
- mov ds,ax
- mov es,ax
- mov ax,[SavedAX]
- pushad
- mov bp,sp ; Point BP to the entry stack frame
- TRACER ''F''
- ; Note: AH =3D=3D P_AH here
- cmp ah,[Int13MaxFunc]
- ja Invalid_jump
- xor al,al ; AL =3D 0 is standard entry condition
- mov di,ax
- shr di,7 ; Convert AH to an offset in DI
- call [Int13Funcs+di]
-
-Done: ; Standard routine for return
- mov P_AX,ax
-DoneWeird:
- TRACER ''D''
- xor bx,bx
- mov es,bx
- mov bx,[StatusPtr]
- mov [es:bx],ah ; Save status
- and ah,ah
-
- lds ebx,[Stack]
- ; This sets the low byte (the arithmetric flags) of the
- ; FLAGS on stack to either 00h (no flags) or 01h (CF)
- ; depending on if AH was zero or not.
- setnz [bx+4] ; Set CF iff error
- popad
- pop es
- pop ds
- lss esp,[cs:Stack]
- iret
-
-Reset:
- ; Reset affects multiple drives, so we need to pass it on
- TRACER ''R''
- xor ax,ax ; Bottom of memory
- mov es,ax
- test dl,dl ; Always pass it on if we are resetting HD
- js .hard_disk ; Bit 7 set
- ; Some BIOSes get very unhappy if we pass a reset floppy
- ; command to them and don''t actually have any floppies.
- ; This is a bug, but we have to deal with it nontheless.
- ; Therefore, if we are the *ONLY* floppy drive, and the
- ; user didn''t request HD reset, then just drop the command.
- ; BIOS equipment byte, top two bits + 1 =3D=3D total # of floppies
- test byte [es:0x410],0C0h
- jz success
- jmp .pass_on ; ... otherwise pass it to the BIOS
-.hard_disk:
- ; ... same thing for hard disks, sigh ...
- cmp byte [es:0x475],1 ; BIOS variable for number of hard disks
- jbe success
-
-.pass_on:
- pop ax ; Drop return address
- popad ; Restore all registers
- pop es
- pop ds
- lss esp,[cs:Stack] ; Restore the stack
- and dl,80h ; Clear all but the type bit
- jmp far [cs:OldInt13]
-
-
-Invalid:
- pop dx ; Drop return address
-Invalid_jump:
- TRACER ''I''
- mov ah,01h ; Unsupported function
- jmp short Done
-
-GetDriveType:
- test byte [DriveNo],80h
- mov bl,02h ; Type 02h =3D floppy with changeline
- jz .floppy
- ; Hard disks only...
- inc bx ; Type =3D 03h
- mov dx,[DiskSize] ; Return the disk size in sectors
- mov P_DX,dx
- mov cx,[DiskSize+2]
- mov P_CX,cx
-.floppy:
- mov P_AH,bl ; 02h floppy, 03h hard disk
- pop ax ; Drop return address
- xor ax,ax ; Success...
- jmp DoneWeird ; But don''t stick it into P_AX
-
-GetStatus:
- xor ax,ax
- mov es,ax
- mov bx,[StatusPtr]
- mov ah,[bx] ; Copy last status
- ret
-
-ReadMult:
- TRACER ''m''
-Read:
- TRACER ''R''
- call setup_regs
-do_copy:
- TRACER ''<''
- call bcopy
- TRACER ''>''
- movzx ax,P_AL ; AH =3D 0, AL =3D transfer count
- ret
-
-WriteMult:
- TRACER ''M''
-Write:
- TRACER ''W''
- test byte [ConfigFlags],CONFIG_READONLY
- jnz .readonly
- call setup_regs
- xchg esi,edi ; Opposite direction of a Read!
- jmp short do_copy
-.readonly: mov ah,03h ; Write protected medium
- ret
-
- ; Verify integrity; just bounds-check
-Seek:
-Verify:
- call setup_regs ; Returns error if appropriate
- ; And fall through to success
-
-CheckIfReady: ; These are always-successful noop functions
-Recalibrate:
-InitWithParms:
-DetectChange:
-EDDDetectChange:
-EDDLock:
-SetMode:
-success:
- xor ax,ax ; Always successful
- ret
-
-GetParms:
- TRACER ''G''
- mov dl,[DriveCnt] ; Cached data
- mov P_DL,dl
- test byte [DriveNo],80h
- jnz .hd
- mov P_DI,DPT
- mov P_ES,cs
- mov bl,[DriveType]
- mov P_BL,bl
-.hd:
- mov ax,[Cylinders]
- dec ax ; We report the highest #, not the count
- xchg al,ah
- shl al,6
- or al,[Sectors]
- mov P_CX,ax
- mov ax,[Heads]
- dec ax
- mov P_DH,al
-
- ;
- ; Is this MEMDISK installation check?
- ;
- cmp P_HAX,''ME''
- jne .notic
- cmp P_HCX,''MD''
- jne .notic
- cmp P_HDX,''IS''
- jne .notic
- cmp P_HBX,''K?''
- jne .notic
-
- ; MEMDISK installation check...
- mov P_HAX,''!M''
- mov P_HCX,''EM''
- mov P_HDX,''DI''
- mov P_HBX,''SK''
- mov P_ES,cs
- mov P_DI,MemDisk_Info
-
-.notic:
- xor ax,ax
- ret
-;
-; EDD functions -- only if enabled
-;
-%if EDD
-EDDPresence:
- TRACER ''E''
- TRACER ''c''
-
- cmp P_BX,55AAh
- jne Invalid
- mov P_BX,0AA55h ; EDD signature
- mov P_AX,03000h ; EDD 3.0
- mov P_CX,0003h ; Bit 0 - Fixed disk access subset
- ; Bit 1 - Locking and ejecting subset
- pop ax ; Drop return address
- xor ax,ax ; Success
- jmp DoneWeird ; Success, but AH !=3D 0, sigh...
-
-EDDRead:
- TRACER ''E''
- TRACER ''r''
-
- call edd_setup_regs
- call bcopy
- xor ax,ax
- ret
-
-EDDWrite:
- TRACER ''E''
- TRACER ''w''
-
- call edd_setup_regs
- xchg esi,edi
- call bcopy
- xor ax,ax
- ret
-
-EDDVerify:
-EDDSeek:
- call edd_setup_regs ; Just bounds checking
- xor ax,ax
- ret
-
-EDDGetParms:
- TRACER ''E''
- TRACER ''p''
-
- mov es,P_DS
- mov di,P_SI
- mov si,EDD_DPT
-
- lodsw ; Length of our DPT
- mov cx,[es:di]
- cmp cx,26 ; Minimum size
- jb .overrun
-
- cmp cx,ax
- jb .oksize
- mov cx,ax
-
-.oksize:
- mov ax,cx
- stosw
- dec cx
- dec cx
- rep movsb
-
- xor ax,ax
- ret
-
-.overrun:
- mov ax,0100h
- ret
-%endif ; EDD
-
- ; Set up registers as for a "Read", and compares against disk size.
- ; WARNING: This fails immediately, even if we can transfer some
- ; sectors. This isn''t really the correct behaviour.
-setup_regs:
-
- ; Convert a CHS address in P_CX/P_DH into an LBA in eax
- ; CH =3D cyl[7:0]
- ; CL[0:5] =3D sector (1-based) CL[7:6] =3D cyl[9:8]
- ; DH =3D head
- movzx ecx,P_CX
- movzx ebx,cl ; Sector number
- and bl,3Fh
- dec ebx ; Sector number is 1-based
- cmp bx,[Sectors]
- jae .overrun
- movzx edi,P_DH ; Head number
- movzx eax,word [Heads]
- cmp di,ax
- jae .overrun
- shr cl,6
- xchg cl,ch ; Now (E)CX <- cylinder number
- mul ecx ; eax <- Heads*cyl# (edx <- 0)
- add eax,edi
- mul dword [Sectors]
- add eax,ebx
- ; Now eax =3D LBA, edx =3D 0
-
- ;
- ; setup_regs continues...
- ;
- ; Note: edi[31:16] and ecx[31:16] =3D 0 already
- mov di,P_BX ; Get linear address of target buffer
- mov cx,P_ES
- shl ecx,4
- add edi,ecx ; EDI =3D address to fetch to
- movzx ecx,P_AL ; Sector count
- mov esi,eax
- add eax,ecx ; LBA of final sector + 1
- shl esi,SECTORSIZE_LG2 ; LBA -> byte offset
- add esi,[DiskBuf] ; Get address in high memory
- cmp eax,[DiskSize] ; Check the high mark against limit
- ja .overrun
- shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords
- ret
-
-.overrun: pop ax ; Drop setup_regs return address
- mov ax,0200h ; Missing address mark
- ret ; Return to Done
-
- ; Set up registers as for an EDD Read, and compares against disk size.
-%if EDD
-edd_setup_regs:
- push es
- mov si,P_SI ; DS:SI -> DAPA
- mov es,P_DS
-
- mov dx,[es:si]
- cmp dx,16
- jb .baddapa
-
- cmp dword [es:si+4],-1
- je .linear_address
-
- movzx ebx,word [es:si+4] ; Offset
- movzx edi,word [es:si+6] ; Segment
- shl edi,4
- add ebx,edi
- jmp .got_address
-
-.linear_address:
- cmp dx,24 ; Must be large enough to hold
- ; linear address
- jb .baddapa
-
- cmp dword [es:si+20],0 ; > 4 GB addresses not supported
- mov ax,0900h ; "Data boundary error" - bogus, but
- ; no really better code available
- jne .error
-
- mov ebx,[es:si+16]
-
-.got_address:
- cmp dword [es:si+12],0 ; LBA too large?
- jne .overrun
-
- movzx ecx, word [es:si+2] ; Sectors to transfer
- mov esi,[es:si+8] ; Starting sector
- mov eax,esi
- add eax,ecx
- jc .overrun
- cmp eax,[DiskSize]
- ja .overrun
-
- shl ecx,SECTORSIZE_LG2-2 ; Convert to dwords
- shl esi,SECTORSIZE_LG2 ; Convert to an offset
- add esi,[DiskBuf]
- mov edi,ebx
- pop es
- ret
-
-.baddapa:
- mov ax,0100h ; Invalid command
- pop es
- pop ax ; Drop setup_regs return address
- ret
-
-.overrun:
- mov ax,0200h ; "Address mark not found" =3D
- ; LBA beyond end of disk
-.error:
- and word [es:si+2],0 ; No sectors transferred
- pop es
- pop ax
- ret
-
-EDDEject:
- mov ax,0B200h ; Volume Not Removable
- ret
-
-%endif ; EDD
-
-
-;
-; INT 15h intercept routines
-;
-int15_e820:
- cmp edx,534D4150h ; "SMAP"
- jne oldint15
- cmp ecx,20 ; Need 20 bytes
- jb err86
- push ds
- push cs
- pop ds
- push edx ; "SMAP"
- and ebx,ebx
- jne .renew
- mov ebx,E820Table
-.renew:
- add bx,16 ; Advance to next
- mov eax,[bx-8] ; Type
- and eax,eax ; Null type?
- jz .renew ; If so advance to next
- mov [es:di+16],eax
- and cl,~3
- cmp ecx,24
- jb .no_extattr
- mov eax,[bx-4] ; Extended attributes
- mov [es:di+20],eax
- mov ecx,24 ; Bytes loaded
-.no_extattr:
- mov eax,[bx-16] ; Start addr (low)
- mov edx,[bx-12] ; Start addr (high)
- mov [es:di],eax
- mov [es:di+4],edx
- mov eax,[bx] ; End addr (low)
- mov edx,[bx+4] ; End addr (high)
- sub eax,[bx-16] ; Derive the length
- sbb edx,[bx-12]
- mov [es:di+8],eax ; Length (low)
- mov [es:di+12],edx ; Length (high)
- cmp dword [bx+8],-1 ; Type of next =3D end?
- jne .notdone
- xor ebx,ebx ; Done with table
-.notdone:
- pop eax ; "SMAP"
- mov edx,eax ; Some systems expect eax =3D edx =3D SMAP
- pop ds
-int15_success:
- mov byte [bp+6], 02h ; Clear CF
- pop bp
- iret
-
-err86:
- mov byte [bp+6], 03h ; Set CF
- mov ah,86h
- pop bp
- iret
-
-Int15Start:
- push bp
- mov bp,sp
- cmp ax,0E820h
- je near int15_e820
- cmp ax,0E801h
- je int15_e801
- cmp ax,0E881h
- je int15_e881
- cmp ah,88h
- je int15_88
-oldint15: pop bp
- jmp far [cs:OldInt15]
-
-int15_e801:
- mov ax,[cs:Mem1MB]
- mov cx,ax
- mov bx,[cs:Mem16MB]
- mov dx,bx
- jmp short int15_success
-
-int15_e881:
- mov eax,[cs:Mem1MB]
- mov ecx,eax
- mov ebx,[cs:Mem16MB]
- mov edx,ebx
- jmp short int15_success
-
-int15_88:
- mov ax,[cs:MemInt1588]
- jmp short int15_success
-
-;
-; Routine to copy in/out of high memory
-; esi =3D linear source address
-; edi =3D linear target address
-; ecx =3D 32-bit word count
-;
-; Assumes cs =3D ds =3D es
-;
-bcopy:
- push eax
- push ebx
- push edx
- push ebp
-
- mov bx, real_int15_stub
-
- test byte [ConfigFlags], CONFIG_RAW|CONFIG_SAFEINT
- jz .anymode ; Always do the real INT 15h
-
- smsw ax ; Unprivileged!
- test al,01h
- jnz .protmode ; Protmode -> do real INT 15h
-
-.realmode:
- ; Raw or Safeint mode, and we''re in real mode...
-
- test byte [ConfigFlags], CONFIG_SAFEINT
- jnz .fakeint15
-
-.raw:
- TRACER ''r''
- ; We''re in real mode, do it outselves
-
- pushfd ; <A>
- push ds ; <B>
- push es ; <C>
-
- cli
- cld
-
- xor ebx,ebx
- mov bx,cs
- shl ebx,4
- lea edx,[Shaker+ebx]
- mov [Shaker+2],edx
-
- ; Test to see if A20 is enabled or not
- xor ax,ax
- mov ds,ax
- dec ax
- mov es,ax
-
- mov ax,[0]
- mov bx,ax
- xor bx,[es:10h]
- not ax
- mov [0],ax
- mov dx,ax
- xor dx,[es:10h]
- not ax
- mov [0],ax
-
- or dx,bx
- push dx ; <D> Save A20 status
- jnz .skip_a20e
-
- mov ax,2401h ; Enable A20
- int 15h
-.skip_a20e:
- mov dl,[ConfigFlags]
- and dx,CONFIG_BIGRAW
- add dx,8
- ; DX =3D 16 for BIGRAW, 8 for RAW
- ; 8 is selector for a 64K flat segment,
- ; 16 is selector for a 4GB flat segment.
-
- lgdt [cs:Shaker]
- mov eax,cr0
- or al,01h
- mov cr0,eax
-
- mov bx,16 ; Large flat segment
- mov ds,bx
- mov es,bx
-
- a32 rep movsd
-
- ; DX has the appropriate value to put in
- ; the registers on return
- mov ds,dx
- mov es,dx
-
- and al,~01h
- mov cr0,eax
-
- pop dx ; <D> A20 status
- pop es ; <C>
- pop ds ; <B>
-
- and dx,dx
- jnz .skip_a20d
- mov ax,2400h ; Disable A20
- int 15h
-.skip_a20d:
- popfd ; <A>
- jmp .done
-
-.fakeint15:
- ; We''re in real mode with CONFIG_SAFEINT, invoke the
- ; original INT 15h vector. We used to test for the
- ; INT 15h vector being unchanged here, but that is
- ; *us*; however, the test was wrong for years (always
- ; negative) so instead of fixing the test do what we
- ; tested and don''t bother probing.
- mov bx, fake_int15_stub
-
-.protmode:
- TRACER ''p''
-.anymode:
-
-.copy_loop:
- push esi
- push edi
- push ecx
- cmp ecx,4000h
- jna .safe_size
- mov ecx,4000h
-.safe_size:
- push ecx ; Transfer size this cycle
- mov eax, esi
- mov [Mover_src1], si
- shr eax, 16
- mov [Mover_src1+2], al
- mov [Mover_src2], ah
- mov eax, edi
- mov [Mover_dst1], di
- shr eax, 16
- mov [Mover_dst1+2], al
- mov [Mover_dst2], ah
- mov si,Mover
- mov ah, 87h
- shl cx,1 ; Convert to 16-bit words
- call bx ; INT 15h stub
- pop eax ; Transfer size this cycle
- pop ecx
- pop edi
- pop esi
- jc .error
- lea esi,[esi+4*eax]
- lea edi,[edi+4*eax]
- sub ecx, eax
- jnz .copy_loop
- ; CF =3D 0
-.error:
-.done:
- pop ebp
- pop edx
- pop ebx
- pop eax
- ret
-
-real_int15_stub:
- int 15h
- cli ; Some BIOSes enable interrupts on INT 15h
- ret
-
-fake_int15_stub:
- pushf
- call far [OldInt15]
- cli
- ret
-
-%ifdef DEBUG_TRACERS
-debug_tracer: pushad
- pushfd
- mov bp,sp
- mov bx,[bp+9*4]
- mov al,[cs:bx]
- inc word [bp+9*4]
- mov ah,0Eh
- mov bx,7
- int 10h
- popfd
- popad
- ret
-%endif
-
- section .data
- alignb 2
-Int13Funcs dw Reset ; 00h - RESET
- dw GetStatus ; 01h - GET STATUS
- dw Read ; 02h - READ
- dw Write ; 03h - WRITE
- dw Verify ; 04h - VERIFY
- dw Invalid ; 05h - FORMAT TRACK
- dw Invalid ; 06h - FORMAT TRACK AND SET BAD FLAGS
- dw Invalid ; 07h - FORMAT DRIVE AT TRACK
- dw GetParms ; 08h - GET PARAMETERS
- dw InitWithParms ; 09h - INITIALIZE CONTROLLER WITH DRIVE PARAMETERS
- dw Invalid ; 0Ah
- dw Invalid ; 0Bh
- dw Seek ; 0Ch - SEEK TO CYLINDER
- dw Reset ; 0Dh - RESET HARD DISKS
- dw Invalid ; 0Eh
- dw Invalid ; 0Fh
- dw CheckIfReady ; 10h - CHECK IF READY
- dw Recalibrate ; 11h - RECALIBRATE
- dw Invalid ; 12h
- dw Invalid ; 13h
- dw Invalid ; 14h
- dw GetDriveType ; 15h - GET DRIVE TYPE
- dw DetectChange ; 16h - DETECT DRIVE CHANGE
-%if EDD
- dw Invalid ; 17h
- dw Invalid ; 18h
- dw Invalid ; 19h
- dw Invalid ; 1Ah
- dw Invalid ; 1Bh
- dw Invalid ; 1Ch
- dw Invalid ; 1Dh
- dw Invalid ; 1Eh
- dw Invalid ; 1Fh
- dw Invalid ; 20h
- dw ReadMult ; 21h - READ MULTIPLE
- dw WriteMult ; 22h - WRITE MULTIPLE
- dw SetMode ; 23h - SET CONTROLLER FEATURES
- dw SetMode ; 24h - SET MULTIPLE MODE
- dw Invalid ; 25h - IDENTIFY DRIVE
- dw Invalid ; 26h
- dw Invalid ; 27h
- dw Invalid ; 28h
- dw Invalid ; 29h
- dw Invalid ; 2Ah
- dw Invalid ; 2Bh
- dw Invalid ; 2Ch
- dw Invalid ; 2Dh
- dw Invalid ; 2Eh
- dw Invalid ; 2Fh
- dw Invalid ; 30h
- dw Invalid ; 31h
- dw Invalid ; 32h
- dw Invalid ; 33h
- dw Invalid ; 34h
- dw Invalid ; 35h
- dw Invalid ; 36h
- dw Invalid ; 37h
- dw Invalid ; 38h
- dw Invalid ; 39h
- dw Invalid ; 3Ah
- dw Invalid ; 3Bh
- dw Invalid ; 3Ch
- dw Invalid ; 3Dh
- dw Invalid ; 3Eh
- dw Invalid ; 3Fh
- dw Invalid ; 40h
- dw EDDPresence ; 41h - EDD PRESENCE DETECT
- dw EDDRead ; 42h - EDD READ
- dw EDDWrite ; 43h - EDD WRITE
- dw EDDVerify ; 44h - EDD VERIFY
- dw EDDLock ; 45h - EDD LOCK/UNLOCK MEDIA
- dw EDDEject ; 46h - EDD EJECT
- dw EDDSeek ; 47h - EDD SEEK
- dw EDDGetParms ; 48h - EDD GET PARAMETERS
- dw EDDDetectChange ; 49h - EDD MEDIA CHANGE STATUS
-%endif
-
-Int13FuncsEnd equ $
-Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1
-
-
- alignb 8, db 0
-Shaker dw ShakerEnd-$
- dd 0 ; Pointer to self
- dw 0
-
-Shaker_RMDS: dd 0x0000ffff ; 64K data segment
- dd 0x00009300
-
-Shaker_DS: dd 0x0000ffff ; 4GB data segment
- dd 0x008f9300
-
-ShakerEnd equ $
-
- alignb 8, db 0
-
-Mover dd 0, 0, 0, 0 ; Must be zero
- dw 0ffffh ; 64 K segment size
-Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy
- db 93h ; Access rights
- db 00h ; Extended access rights
-Mover_src2: db 0 ; High 8 bits of source addy
- dw 0ffffh ; 64 K segment size
-Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy
- db 93h ; Access rights
- db 00h ; Extended access rights
-Mover_dst2: db 0 ; High 8 bits of source addy
-Mover_dummy2: dd 0, 0, 0, 0 ; More space for the BIOS
-
- alignb 4, db 0
-MemDisk_Info equ $ ; Pointed to by installation check
-MDI_Bytes dw MDI_Len ; Total bytes in MDI structure
-MDI_Version db VERSION_MINOR, VERSION_MAJOR ; MEMDISK version
-
-PatchArea equ $ ; This gets filled in by the installer
-
-DiskBuf dd 0 ; Linear address of high memory disk
-DiskSize dd 0 ; Size of disk in blocks
-CommandLine dw 0, 0 ; Far pointer to saved command line
-
-OldInt13 dd 0 ; INT 13h in chain
-OldInt15 dd 0 ; INT 15h in chain
-
-OldDosMem dw 0 ; Old position of DOS mem end
-BootLoaderID db 0 ; Boot loader ID from header
- db 0 ; pad
-
-DPT_ptr dw 0 ; If nonzero, pointer to DPT
- ; Original DPT pointer follows
-
-MDI_Len equ $-MemDisk_Info
-
-; ---- MDI structure ends here ---
-Int13MaxFunc db Int13FuncsCnt-1 ; Max INT 13h function (to disable EDD)
- db 0 ; pad
-
- dw 0 ; pad
-MemInt1588 dw 0 ; 1MB-65MB memory amount (1K)
-
-Cylinders dw 0 ; Cylinder count
-Heads dw 0 ; Head count
-Sectors dd 0 ; Sector count (zero-extended)
-
-Mem1MB dd 0 ; 1MB-16MB memory amount (1K)
-Mem16MB dd 0 ; 16MB-4G memory amount (64K)
-
-DriveNo db 0 ; Our drive number
-DriveType db 0 ; Our drive type (floppies)
-DriveCnt db 0 ; Drive count (from the BIOS)
-
-ConfigFlags db 0 ; Bit 0 - readonly
-
-MyStack dw 0 ; Offset of stack
-StatusPtr dw 0 ; Where to save status (zeroseg ptr)
-
-DPT times 16 db 0 ; BIOS parameter table pointer (floppies)
-OldInt1E dd 0 ; Previous INT 1E pointer (DPT)
-
-%if EDD
-EDD_DPT:
-.length dw 30
-.info dw 0029h
- ; Bit 0 - DMA boundaries handled transparently
- ; Bit 3 - Device supports write verify
- ; Bit 5 - Media is lockable
-.cylinders dd 0 ; Filled in by installer
-.heads dd 0 ; Filled in by installer
-.sectors dd 0 ; Filled in by installer
-.totalsize dd 0, 0 ; Filled in by installer
-.bytespersec dw SECTORSIZE
-.eddtable dw -1, -1 ; Invalid DPTE pointer
-
-%endif
-
- ; End patch area
-Stack dd 0 ; Saved SS:ESP on invocation
- dw 0
-SavedAX dw 0 ; AX saved on invocation
-
- alignb 4, db 0 ; We *MUST* end on a dword boundary
-
-E820Table equ $ ; The installer loads the E820 table here
-TotalSize equ $ ; End pointer
+%include "memdisk.inc"
diff --git a/memdisk/memdisk.inc b/memdisk/memdisk.inc
new file mode 100644
index 0000000..2b5b4e0
--- /dev/null
+++ b/memdisk/memdisk.inc
@@ -0,0 +1,987 @@
+; -*- fundamental -*- (asm-mode sucks)
+; ****************************************************************************
+;
+; memdisk.inc
+;
+; A program to emulate an INT 13h disk BIOS from a "disk" in
extended
+; memory.
+;
+; Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+; Boston MA 02111-1307, USA; either version 2 of the License, or
+; (at your option) any later version; incorporated herein by reference.
+;
+; ****************************************************************************
+
+%ifndef DEPEND
+%include "../version.gen"
+%endif
+
+; %define DEBUG_TRACERS ; Uncomment to get debugging tracers
+
+%ifdef WITH_EDD
+%define EDD 1
+%else
+%define EDD 0
+%endif
+
+%ifdef DEBUG_TRACERS
+
+%macro TRACER 1
+ call debug_tracer
+ db %1
+%endmacro
+
+%else ; DEBUG_TRACERS
+
+%macro TRACER 1
+%endmacro
+
+%endif ; DEBUG_TRACERS
+
+%define CONFIG_READONLY 0x01
+%define CONFIG_RAW 0x02
+%define CONFIG_SAFEINT 0x04
+%define CONFIG_BIGRAW 0x08 ; MUST be 8!
+
+ org 0h
+
+%define SECTORSIZE_LG2 9 ; log2(sector size)
+%define SECTORSIZE (1 << SECTORSIZE_LG2)
+
+ ; Parameter registers definition; this is the definition
+ ; of the stack frame.
+%define P_DS word [bp+34]
+%define P_ES word [bp+32]
+%define P_EAX dword [bp+28]
+%define P_HAX word [bp+30]
+%define P_AX word [bp+28]
+%define P_AL byte [bp+28]
+%define P_AH byte [bp+29]
+%define P_ECX dword [bp+24]
+%define P_HCX word [bp+26]
+%define P_CX word [bp+24]
+%define P_CL byte [bp+24]
+%define P_CH byte [bp+25]
+%define P_EDX dword [bp+20]
+%define P_HDX word [bp+22]
+%define P_DX word [bp+20]
+%define P_DL byte [bp+20]
+%define P_DH byte [bp+21]
+%define P_EBX dword [bp+16]
+%define P_HBX word [bp+18]
+%define P_HBXL byte [bp+18]
+%define P_BX word [bp+16]
+%define P_BL byte [bp+16]
+%define P_BH byte [bp+17]
+%define P_EBP dword [bp+8]
+%define P_BP word [bp+8]
+%define P_ESI dword [bp+4]
+%define P_SI word [bp+4]
+%define P_EDI dword [bp]
+%define P_DI word [bp]
+
+ section .text
+ ; These pointers are used by the installer and
+ ; must be first in the binary
+Pointers: dw Int13Start
+ dw Int15Start
+ dw PatchArea
+ dw TotalSize
+ dw IretPtr
+
+IretPtr equ Int13Start.iret
+Int13Start:
+ ; Swap stack
+ mov [cs:Stack],esp
+ mov [cs:SavedAX],ax
+ mov ax,ss
+ mov [cs:Stack+4],ax
+ mov ax,cs
+ mov ss,ax
+ mov sp,[cs:MyStack]
+
+ ; See if DL points to our class of device (FD, HD)
+ push dx
+ push dx
+ xor dl,[cs:DriveNo]
+ pop dx
+ js .nomatch ; If SF=3D0, we have a class match here
+ jz .our_drive ; If ZF=3D1, we have an exact match
+ cmp dl,[cs:DriveNo]
+ jb .nomatch ; Drive < Our drive
+ dec dl ; Drive > Our drive, adjust drive #
+.nomatch:
+ mov ax,[cs:SavedAX]
+ pushf
+ call far [cs:OldInt13]
+ pushf
+ push bp
+ mov bp,sp
+ cmp byte [cs:SavedAX+1],08h
+ je .norestoredl
+ cmp byte [cs:SavedAX+1],15h
+ jne .restoredl
+ test byte [bp+4],80h ; Hard disk?
+ jnz .norestoredl
+.restoredl:
+ mov dl,[bp+4]
+.norestoredl:
+ push ax
+ push ebx
+ push ds
+ mov ax,[bp+2] ; Flags
+ lds ebx,[cs:Stack]
+ mov [bx+4],al ; Arithmetric flags
+ pop ds
+ pop ebx
+ pop ax
+ pop bp
+ lss esp,[cs:Stack]
+.iret: iret
+
+.our_drive:
+ ; Set up standard entry frame
+ push ds
+ push es
+ mov ds,ax
+ mov es,ax
+ mov ax,[SavedAX]
+ pushad
+ mov bp,sp ; Point BP to the entry stack frame
+ TRACER ''F''
+ ; Note: AH =3D=3D P_AH here
+ cmp ah,[Int13MaxFunc]
+ ja Invalid_jump
+ xor al,al ; AL =3D 0 is standard entry condition
+ mov di,ax
+ shr di,7 ; Convert AH to an offset in DI
+ call [Int13Funcs+di]
+
+Done: ; Standard routine for return
+ mov P_AX,ax
+DoneWeird:
+ TRACER ''D''
+ xor bx,bx
+ mov es,bx
+ mov bx,[StatusPtr]
+ mov [es:bx],ah ; Save status
+ and ah,ah
+
+ lds ebx,[Stack]
+ ; This sets the low byte (the arithmetric flags) of the
+ ; FLAGS on stack to either 00h (no flags) or 01h (CF)
+ ; depending on if AH was zero or not.
+ setnz [bx+4] ; Set CF iff error
+ popad
+ pop es
+ pop ds
+ lss esp,[cs:Stack]
+ iret
+
+Reset:
+ ; Reset affects multiple drives, so we need to pass it on
+ TRACER ''R''
+ xor ax,ax ; Bottom of memory
+ mov es,ax
+ test dl,dl ; Always pass it on if we are resetting HD
+ js .hard_disk ; Bit 7 set
+ ; Some BIOSes get very unhappy if we pass a reset floppy
+ ; command to them and don''t actually have any floppies.
+ ; This is a bug, but we have to deal with it nontheless.
+ ; Therefore, if we are the *ONLY* floppy drive, and the
+ ; user didn''t request HD reset, then just drop the command.
+ ; BIOS equipment byte, top two bits + 1 =3D=3D total # of floppies
+ test byte [es:0x410],0C0h
+ jz success
+ jmp .pass_on ; ... otherwise pass it to the BIOS
+.hard_disk:
+ ; ... same thing for hard disks, sigh ...
+ cmp byte [es:0x475],1 ; BIOS variable for number of hard disks
+ jbe success
+
+.pass_on:
+ pop ax ; Drop return address
+ popad ; Restore all registers
+ pop es
+ pop ds
+ lss esp,[cs:Stack] ; Restore the stack
+ and dl,80h ; Clear all but the type bit
+ jmp far [cs:OldInt13]
+
+
+Invalid:
+ pop dx ; Drop return address
+Invalid_jump:
+ TRACER ''I''
+ mov ah,01h ; Unsupported function
+ jmp short Done
+
+GetDriveType:
+ test byte [DriveNo],80h
+ mov bl,02h ; Type 02h =3D floppy with changeline
+ jz .floppy
+ ; Hard disks only...
+ inc bx ; Type =3D 03h
+ mov dx,[DiskSize] ; Return the disk size in sectors
+ mov P_DX,dx
+ mov cx,[DiskSize+2]
+ mov P_CX,cx
+.floppy:
+ mov P_AH,bl ; 02h floppy, 03h hard disk
+ pop ax ; Drop return address
+ xor ax,ax ; Success...
+ jmp DoneWeird ; But don''t stick it into P_AX
+
+GetStatus:
+ xor ax,ax
+ mov es,ax
+ mov bx,[StatusPtr]
+ mov ah,[bx] ; Copy last status
+ ret
+
+ReadMult:
+ TRACER ''m''
+Read:
+ TRACER ''R''
+ call setup_regs
+do_copy:
+ TRACER ''<''
+ call bcopy
+ TRACER ''>''
+ movzx ax,P_AL ; AH =3D 0, AL =3D transfer count
+ ret
+
+WriteMult:
+ TRACER ''M''
+Write:
+ TRACER ''W''
+ test byte [ConfigFlags],CONFIG_READONLY
+ jnz .readonly
+ call setup_regs
+ xchg esi,edi ; Opposite direction of a Read!
+ jmp short do_copy
+.readonly: mov ah,03h ; Write protected medium
+ ret
+
+ ; Verify integrity; just bounds-check
+Seek:
+Verify:
+ call setup_regs ; Returns error if appropriate
+ ; And fall through to success
+
+CheckIfReady: ; These are always-successful noop functions
+Recalibrate:
+InitWithParms:
+DetectChange:
+EDDDetectChange:
+EDDLock:
+SetMode:
+success:
+ xor ax,ax ; Always successful
+ ret
+
+GetParms:
+ TRACER ''G''
+ mov dl,[DriveCnt] ; Cached data
+ mov P_DL,dl
+ test byte [DriveNo],80h
+ jnz .hd
+ mov P_DI,DPT
+ mov P_ES,cs
+ mov bl,[DriveType]
+ mov P_BL,bl
+.hd:
+ mov ax,[Cylinders]
+ dec ax ; We report the highest #, not the count
+ xchg al,ah
+ shl al,6
+ or al,[Sectors]
+ mov P_CX,ax
+ mov ax,[Heads]
+ dec ax
+ mov P_DH,al
+
+ ;
+ ; Is this MEMDISK installation check?
+ ;
+ cmp P_HAX,''ME''
+ jne .notic
+ cmp P_HCX,''MD''
+ jne .notic
+ cmp P_HDX,''IS''
+ jne .notic
+ cmp P_HBX,''K?''
+ jne .notic
+
+ ; MEMDISK installation check...
+ mov P_HAX,''!M''
+ mov P_HCX,''EM''
+ mov P_HDX,''DI''
+ mov P_HBX,''SK''
+ mov P_ES,cs
+ mov P_DI,MemDisk_Info
+
+.notic:
+ xor ax,ax
+ ret
+;
+; EDD functions -- only if enabled
+;
+%if EDD
+EDDPresence:
+ TRACER ''E''
+ TRACER ''c''
+
+ cmp P_BX,55AAh
+ jne Invalid
+ mov P_BX,0AA55h ; EDD signature
+ mov P_AX,03000h ; EDD 3.0
+ mov P_CX,0003h ; Bit 0 - Fixed disk access subset
+ ; Bit 1 - Locking and ejecting subset
+ pop ax ; Drop return address
+ xor ax,ax ; Success
+ jmp DoneWeird ; Success, but AH !=3D 0, sigh...
+
+EDDRead:
+ TRACER ''E''
+ TRACER ''r''
+
+ call edd_setup_regs
+ call bcopy
+ xor ax,ax
+ ret
+
+EDDWrite:
+ TRACER ''E''
+ TRACER ''w''
+
+ call edd_setup_regs
+ xchg esi,edi
+ call bcopy
+ xor ax,ax
+ ret
+
+EDDVerify:
+EDDSeek:
+ call edd_setup_regs ; Just bounds checking
+ xor ax,ax
+ ret
+
+EDDGetParms:
+ TRACER ''E''
+ TRACER ''p''
+
+ mov es,P_DS
+ mov di,P_SI
+ mov si,EDD_DPT
+
+ lodsw ; Length of our DPT
+ mov cx,[es:di]
+ cmp cx,26 ; Minimum size
+ jb .overrun
+
+ cmp cx,ax
+ jb .oksize
+ mov cx,ax
+
+.oksize:
+ mov ax,cx
+ stosw
+ dec cx
+ dec cx
+ rep movsb
+
+ xor ax,ax
+ ret
+
+.overrun:
+ mov ax,0100h
+ ret
+%endif ; EDD
+
+ ; Set up registers as for a "Read", and compares against disk size.
+ ; WARNING: This fails immediately, even if we can transfer some
+ ; sectors. This isn''t really the correct behaviour.
+setup_regs:
+
+ ; Convert a CHS address in P_CX/P_DH into an LBA in eax
+ ; CH =3D cyl[7:0]
+ ; CL[0:5] =3D sector (1-based) CL[7:6] =3D cyl[9:8]
+ ; DH =3D head
+ movzx ecx,P_CX
+ movzx ebx,cl ; Sector number
+ and bl,3Fh
+ dec ebx ; Sector number is 1-based
+ cmp bx,[Sectors]
+ jae .overrun
+ movzx edi,P_DH ; Head number
+ movzx eax,word [Heads]
+ cmp di,ax
+ jae .overrun
+ shr cl,6
+ xchg cl,ch ; Now (E)CX <- cylinder number
+ mul ecx ; eax <- Heads*cyl# (edx <- 0)
+ add eax,edi
+ mul dword [Sectors]
+ add eax,ebx
+ ; Now eax =3D LBA, edx =3D 0
+
+ ;
+ ; setup_regs continues...
+ ;
+ ; Note: edi[31:16] and ecx[31:16] =3D 0 already
+ mov di,P_BX ; Get linear address of target buffer
+ mov cx,P_ES
+ shl ecx,4
+ add edi,ecx ; EDI =3D address to fetch to
+ movzx ecx,P_AL ; Sector count
+ mov esi,eax
+ add eax,ecx ; LBA of final sector + 1
+ shl esi,SECTORSIZE_LG2 ; LBA -> byte offset
+ add esi,[DiskBuf] ; Get address in high memory
+ cmp eax,[DiskSize] ; Check the high mark against limit
+ ja .overrun
+ shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords
+ ret
+
+.overrun: pop ax ; Drop setup_regs return address
+ mov ax,0200h ; Missing address mark
+ ret ; Return to Done
+
+ ; Set up registers as for an EDD Read, and compares against disk size.
+%if EDD
+edd_setup_regs:
+ push es
+ mov si,P_SI ; DS:SI -> DAPA
+ mov es,P_DS
+
+ mov dx,[es:si]
+ cmp dx,16
+ jb .baddapa
+
+ cmp dword [es:si+4],-1
+ je .linear_address
+
+ movzx ebx,word [es:si+4] ; Offset
+ movzx edi,word [es:si+6] ; Segment
+ shl edi,4
+ add ebx,edi
+ jmp .got_address
+
+.linear_address:
+ cmp dx,24 ; Must be large enough to hold
+ ; linear address
+ jb .baddapa
+
+ cmp dword [es:si+20],0 ; > 4 GB addresses not supported
+ mov ax,0900h ; "Data boundary error" - bogus, but
+ ; no really better code available
+ jne .error
+
+ mov ebx,[es:si+16]
+
+.got_address:
+ cmp dword [es:si+12],0 ; LBA too large?
+ jne .overrun
+
+ movzx ecx, word [es:si+2] ; Sectors to transfer
+ mov esi,[es:si+8] ; Starting sector
+ mov eax,esi
+ add eax,ecx
+ jc .overrun
+ cmp eax,[DiskSize]
+ ja .overrun
+
+ shl ecx,SECTORSIZE_LG2-2 ; Convert to dwords
+ shl esi,SECTORSIZE_LG2 ; Convert to an offset
+ add esi,[DiskBuf]
+ mov edi,ebx
+ pop es
+ ret
+
+.baddapa:
+ mov ax,0100h ; Invalid command
+ pop es
+ pop ax ; Drop setup_regs return address
+ ret
+
+.overrun:
+ mov ax,0200h ; "Address mark not found" =3D
+ ; LBA beyond end of disk
+.error:
+ and word [es:si+2],0 ; No sectors transferred
+ pop es
+ pop ax
+ ret
+
+EDDEject:
+ mov ax,0B200h ; Volume Not Removable
+ ret
+
+%endif ; EDD
+
+
+;
+; INT 15h intercept routines
+;
+int15_e820:
+ cmp edx,534D4150h ; "SMAP"
+ jne oldint15
+ cmp ecx,20 ; Need 20 bytes
+ jb err86
+ push ds
+ push cs
+ pop ds
+ push edx ; "SMAP"
+ and ebx,ebx
+ jne .renew
+ mov ebx,E820Table
+.renew:
+ add bx,16 ; Advance to next
+ mov eax,[bx-8] ; Type
+ and eax,eax ; Null type?
+ jz .renew ; If so advance to next
+ mov [es:di+16],eax
+ and cl,~3
+ cmp ecx,24
+ jb .no_extattr
+ mov eax,[bx-4] ; Extended attributes
+ mov [es:di+20],eax
+ mov ecx,24 ; Bytes loaded
+.no_extattr:
+ mov eax,[bx-16] ; Start addr (low)
+ mov edx,[bx-12] ; Start addr (high)
+ mov [es:di],eax
+ mov [es:di+4],edx
+ mov eax,[bx] ; End addr (low)
+ mov edx,[bx+4] ; End addr (high)
+ sub eax,[bx-16] ; Derive the length
+ sbb edx,[bx-12]
+ mov [es:di+8],eax ; Length (low)
+ mov [es:di+12],edx ; Length (high)
+ cmp dword [bx+8],-1 ; Type of next =3D end?
+ jne .notdone
+ xor ebx,ebx ; Done with table
+.notdone:
+ pop eax ; "SMAP"
+ mov edx,eax ; Some systems expect eax =3D edx =3D SMAP
+ pop ds
+int15_success:
+ mov byte [bp+6], 02h ; Clear CF
+ pop bp
+ iret
+
+err86:
+ mov byte [bp+6], 03h ; Set CF
+ mov ah,86h
+ pop bp
+ iret
+
+Int15Start:
+ push bp
+ mov bp,sp
+ cmp ax,0E820h
+ je near int15_e820
+ cmp ax,0E801h
+ je int15_e801
+ cmp ax,0E881h
+ je int15_e881
+ cmp ah,88h
+ je int15_88
+oldint15: pop bp
+ jmp far [cs:OldInt15]
+
+int15_e801:
+ mov ax,[cs:Mem1MB]
+ mov cx,ax
+ mov bx,[cs:Mem16MB]
+ mov dx,bx
+ jmp short int15_success
+
+int15_e881:
+ mov eax,[cs:Mem1MB]
+ mov ecx,eax
+ mov ebx,[cs:Mem16MB]
+ mov edx,ebx
+ jmp short int15_success
+
+int15_88:
+ mov ax,[cs:MemInt1588]
+ jmp short int15_success
+
+;
+; Routine to copy in/out of high memory
+; esi =3D linear source address
+; edi =3D linear target address
+; ecx =3D 32-bit word count
+;
+; Assumes cs =3D ds =3D es
+;
+bcopy:
+ push eax
+ push ebx
+ push edx
+ push ebp
+
+ mov bx, real_int15_stub
+
+ test byte [ConfigFlags], CONFIG_RAW|CONFIG_SAFEINT
+ jz .anymode ; Always do the real INT 15h
+
+ smsw ax ; Unprivileged!
+ test al,01h
+ jnz .protmode ; Protmode -> do real INT 15h
+
+.realmode:
+ ; Raw or Safeint mode, and we''re in real mode...
+
+ test byte [ConfigFlags], CONFIG_SAFEINT
+ jnz .fakeint15
+
+.raw:
+ TRACER ''r''
+ ; We''re in real mode, do it outselves
+
+ pushfd ; <A>
+ push ds ; <B>
+ push es ; <C>
+
+ cli
+ cld
+
+ xor ebx,ebx
+ mov bx,cs
+ shl ebx,4
+ lea edx,[Shaker+ebx]
+ mov [Shaker+2],edx
+
+ ; Test to see if A20 is enabled or not
+ xor ax,ax
+ mov ds,ax
+ dec ax
+ mov es,ax
+
+ mov ax,[0]
+ mov bx,ax
+ xor bx,[es:10h]
+ not ax
+ mov [0],ax
+ mov dx,ax
+ xor dx,[es:10h]
+ not ax
+ mov [0],ax
+
+ or dx,bx
+ push dx ; <D> Save A20 status
+ jnz .skip_a20e
+
+ mov ax,2401h ; Enable A20
+ int 15h
+.skip_a20e:
+ mov dl,[ConfigFlags]
+ and dx,CONFIG_BIGRAW
+ add dx,8
+ ; DX =3D 16 for BIGRAW, 8 for RAW
+ ; 8 is selector for a 64K flat segment,
+ ; 16 is selector for a 4GB flat segment.
+
+ lgdt [cs:Shaker]
+ mov eax,cr0
+ or al,01h
+ mov cr0,eax
+
+ mov bx,16 ; Large flat segment
+ mov ds,bx
+ mov es,bx
+
+ a32 rep movsd
+
+ ; DX has the appropriate value to put in
+ ; the registers on return
+ mov ds,dx
+ mov es,dx
+
+ and al,~01h
+ mov cr0,eax
+
+ pop dx ; <D> A20 status
+ pop es ; <C>
+ pop ds ; <B>
+
+ and dx,dx
+ jnz .skip_a20d
+ mov ax,2400h ; Disable A20
+ int 15h
+.skip_a20d:
+ popfd ; <A>
+ jmp .done
+
+.fakeint15:
+ ; We''re in real mode with CONFIG_SAFEINT, invoke the
+ ; original INT 15h vector. We used to test for the
+ ; INT 15h vector being unchanged here, but that is
+ ; *us*; however, the test was wrong for years (always
+ ; negative) so instead of fixing the test do what we
+ ; tested and don''t bother probing.
+ mov bx, fake_int15_stub
+
+.protmode:
+ TRACER ''p''
+.anymode:
+
+.copy_loop:
+ push esi
+ push edi
+ push ecx
+ cmp ecx,4000h
+ jna .safe_size
+ mov ecx,4000h
+.safe_size:
+ push ecx ; Transfer size this cycle
+ mov eax, esi
+ mov [Mover_src1], si
+ shr eax, 16
+ mov [Mover_src1+2], al
+ mov [Mover_src2], ah
+ mov eax, edi
+ mov [Mover_dst1], di
+ shr eax, 16
+ mov [Mover_dst1+2], al
+ mov [Mover_dst2], ah
+ mov si,Mover
+ mov ah, 87h
+ shl cx,1 ; Convert to 16-bit words
+ call bx ; INT 15h stub
+ pop eax ; Transfer size this cycle
+ pop ecx
+ pop edi
+ pop esi
+ jc .error
+ lea esi,[esi+4*eax]
+ lea edi,[edi+4*eax]
+ sub ecx, eax
+ jnz .copy_loop
+ ; CF =3D 0
+.error:
+.done:
+ pop ebp
+ pop edx
+ pop ebx
+ pop eax
+ ret
+
+real_int15_stub:
+ int 15h
+ cli ; Some BIOSes enable interrupts on INT 15h
+ ret
+
+fake_int15_stub:
+ pushf
+ call far [OldInt15]
+ cli
+ ret
+
+%ifdef DEBUG_TRACERS
+debug_tracer: pushad
+ pushfd
+ mov bp,sp
+ mov bx,[bp+9*4]
+ mov al,[cs:bx]
+ inc word [bp+9*4]
+ mov ah,0Eh
+ mov bx,7
+ int 10h
+ popfd
+ popad
+ ret
+%endif
+
+ section .data
+ alignb 2
+Int13Funcs dw Reset ; 00h - RESET
+ dw GetStatus ; 01h - GET STATUS
+ dw Read ; 02h - READ
+ dw Write ; 03h - WRITE
+ dw Verify ; 04h - VERIFY
+ dw Invalid ; 05h - FORMAT TRACK
+ dw Invalid ; 06h - FORMAT TRACK AND SET BAD FLAGS
+ dw Invalid ; 07h - FORMAT DRIVE AT TRACK
+ dw GetParms ; 08h - GET PARAMETERS
+ dw InitWithParms ; 09h - INITIALIZE CONTROLLER WITH DRIVE PARAMETERS
+ dw Invalid ; 0Ah
+ dw Invalid ; 0Bh
+ dw Seek ; 0Ch - SEEK TO CYLINDER
+ dw Reset ; 0Dh - RESET HARD DISKS
+ dw Invalid ; 0Eh
+ dw Invalid ; 0Fh
+ dw CheckIfReady ; 10h - CHECK IF READY
+ dw Recalibrate ; 11h - RECALIBRATE
+ dw Invalid ; 12h
+ dw Invalid ; 13h
+ dw Invalid ; 14h
+ dw GetDriveType ; 15h - GET DRIVE TYPE
+ dw DetectChange ; 16h - DETECT DRIVE CHANGE
+%if EDD
+ dw Invalid ; 17h
+ dw Invalid ; 18h
+ dw Invalid ; 19h
+ dw Invalid ; 1Ah
+ dw Invalid ; 1Bh
+ dw Invalid ; 1Ch
+ dw Invalid ; 1Dh
+ dw Invalid ; 1Eh
+ dw Invalid ; 1Fh
+ dw Invalid ; 20h
+ dw ReadMult ; 21h - READ MULTIPLE
+ dw WriteMult ; 22h - WRITE MULTIPLE
+ dw SetMode ; 23h - SET CONTROLLER FEATURES
+ dw SetMode ; 24h - SET MULTIPLE MODE
+ dw Invalid ; 25h - IDENTIFY DRIVE
+ dw Invalid ; 26h
+ dw Invalid ; 27h
+ dw Invalid ; 28h
+ dw Invalid ; 29h
+ dw Invalid ; 2Ah
+ dw Invalid ; 2Bh
+ dw Invalid ; 2Ch
+ dw Invalid ; 2Dh
+ dw Invalid ; 2Eh
+ dw Invalid ; 2Fh
+ dw Invalid ; 30h
+ dw Invalid ; 31h
+ dw Invalid ; 32h
+ dw Invalid ; 33h
+ dw Invalid ; 34h
+ dw Invalid ; 35h
+ dw Invalid ; 36h
+ dw Invalid ; 37h
+ dw Invalid ; 38h
+ dw Invalid ; 39h
+ dw Invalid ; 3Ah
+ dw Invalid ; 3Bh
+ dw Invalid ; 3Ch
+ dw Invalid ; 3Dh
+ dw Invalid ; 3Eh
+ dw Invalid ; 3Fh
+ dw Invalid ; 40h
+ dw EDDPresence ; 41h - EDD PRESENCE DETECT
+ dw EDDRead ; 42h - EDD READ
+ dw EDDWrite ; 43h - EDD WRITE
+ dw EDDVerify ; 44h - EDD VERIFY
+ dw EDDLock ; 45h - EDD LOCK/UNLOCK MEDIA
+ dw EDDEject ; 46h - EDD EJECT
+ dw EDDSeek ; 47h - EDD SEEK
+ dw EDDGetParms ; 48h - EDD GET PARAMETERS
+ dw EDDDetectChange ; 49h - EDD MEDIA CHANGE STATUS
+%endif
+
+Int13FuncsEnd equ $
+Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1
+
+
+ alignb 8, db 0
+Shaker dw ShakerEnd-$
+ dd 0 ; Pointer to self
+ dw 0
+
+Shaker_RMDS: dd 0x0000ffff ; 64K data segment
+ dd 0x00009300
+
+Shaker_DS: dd 0x0000ffff ; 4GB data segment
+ dd 0x008f9300
+
+ShakerEnd equ $
+
+ alignb 8, db 0
+
+Mover dd 0, 0, 0, 0 ; Must be zero
+ dw 0ffffh ; 64 K segment size
+Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy
+ db 93h ; Access rights
+ db 00h ; Extended access rights
+Mover_src2: db 0 ; High 8 bits of source addy
+ dw 0ffffh ; 64 K segment size
+Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy
+ db 93h ; Access rights
+ db 00h ; Extended access rights
+Mover_dst2: db 0 ; High 8 bits of source addy
+Mover_dummy2: dd 0, 0, 0, 0 ; More space for the BIOS
+
+ alignb 4, db 0
+MemDisk_Info equ $ ; Pointed to by installation check
+MDI_Bytes dw MDI_Len ; Total bytes in MDI structure
+MDI_Version db VERSION_MINOR, VERSION_MAJOR ; MEMDISK version
+
+PatchArea equ $ ; This gets filled in by the installer
+
+DiskBuf dd 0 ; Linear address of high memory disk
+DiskSize dd 0 ; Size of disk in blocks
+CommandLine dw 0, 0 ; Far pointer to saved command line
+
+OldInt13 dd 0 ; INT 13h in chain
+OldInt15 dd 0 ; INT 15h in chain
+
+OldDosMem dw 0 ; Old position of DOS mem end
+BootLoaderID db 0 ; Boot loader ID from header
+ db 0 ; pad
+
+DPT_ptr dw 0 ; If nonzero, pointer to DPT
+ ; Original DPT pointer follows
+
+MDI_Len equ $-MemDisk_Info
+
+; ---- MDI structure ends here ---
+Int13MaxFunc db Int13FuncsCnt-1 ; Max INT 13h function (to disable EDD)
+ db 0 ; pad
+
+ dw 0 ; pad
+MemInt1588 dw 0 ; 1MB-65MB memory amount (1K)
+
+Cylinders dw 0 ; Cylinder count
+Heads dw 0 ; Head count
+Sectors dd 0 ; Sector count (zero-extended)
+
+Mem1MB dd 0 ; 1MB-16MB memory amount (1K)
+Mem16MB dd 0 ; 16MB-4G memory amount (64K)
+
+DriveNo db 0 ; Our drive number
+DriveType db 0 ; Our drive type (floppies)
+DriveCnt db 0 ; Drive count (from the BIOS)
+
+ConfigFlags db 0 ; Bit 0 - readonly
+
+MyStack dw 0 ; Offset of stack
+StatusPtr dw 0 ; Where to save status (zeroseg ptr)
+
+DPT times 16 db 0 ; BIOS parameter table pointer (floppies)
+OldInt1E dd 0 ; Previous INT 1E pointer (DPT)
+
+%if EDD
+EDD_DPT:
+.length dw 30
+.info dw 0029h
+ ; Bit 0 - DMA boundaries handled transparently
+ ; Bit 3 - Device supports write verify
+ ; Bit 5 - Media is lockable
+.cylinders dd 0 ; Filled in by installer
+.heads dd 0 ; Filled in by installer
+.sectors dd 0 ; Filled in by installer
+.totalsize dd 0, 0 ; Filled in by installer
+.bytespersec dw SECTORSIZE
+.eddtable dw -1, -1 ; Invalid DPTE pointer
+
+%endif
+
+ ; End patch area
+Stack dd 0 ; Saved SS:ESP on invocation
+ dw 0
+SavedAX dw 0 ; AX saved on invocation
+
+ alignb 4, db 0 ; We *MUST* end on a dword boundary
+
+E820Table equ $ ; The installer loads the E820 table here
+TotalSize equ $ ; End pointer
diff --git a/memdisk/memdisk_edd.asm b/memdisk/memdisk_edd.asm
new file mode 100644
index 0000000..97d3fe9
--- /dev/null
+++ b/memdisk/memdisk_edd.asm
@@ -0,0 +1,2 @@
+%define WITH_EDD
+%include "memdisk.inc"
diff --git a/memdisk/setup.c b/memdisk/setup.c
index 7b1f456..ed08d57 100644
--- a/memdisk/setup.c
+++ b/memdisk/setup.c
@@ -24,6 +24,9 @@ const char copyright[] =3D
=20
extern const char _binary_memdisk_bin_start[], _binary_memdisk_bin_end[];
extern const char _binary_memdisk_bin_size[]; /* Weird, I know */
+extern const char _binary_memdisk_edd_bin_start[],
+ _binary_memdisk_edd_end[];
+extern const char _binary_memdisk_edd_bin_size[];
=20
struct memdisk_header {
uint16_t int13_offs;
@@ -93,7 +96,6 @@ struct patch_area {
uint16_t dpt_ptr;
/* End of the official MemDisk_Info */
uint8_t maxint13func;
-#define MAXINT13_NOEDD 0x16
uint8_t _pad2;
=20
uint16_t _pad3;
@@ -598,7 +600,8 @@ void *sys_bounce;
=20
__cdecl void setup(__cdecl syscall_t cs_syscall, void *cs_bounce)
{
- unsigned int bin_size =3D (int) &_binary_memdisk_bin_size;
+ unsigned int bin_size;
+ char *memdisk_hook;
struct memdisk_header *hptr;
struct patch_area *pptr;
uint16_t driverseg;
@@ -610,7 +613,7 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void
*cs_bounce)
com32sys_t regs;
uint32_t ramdisk_image, ramdisk_size;
int bios_drives;
- int do_edd =3D -1; /* -1 =3D default, 0 =3D no, 1 =3D yes */
+ int do_edd =3D 1; /* 0 =3D no, 1 =3D yes, default is yes */
int no_bpt; /* No valid BPT presented */
=20
/* Set up global variables */
@@ -649,13 +652,22 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void
*cs_bounce)
else
do_edd =3D (geometry->driveno & 0x80) ? 1 : 0;
=20
+ /* Choose the appropriate installable memdisk hook */
+ if (do_edd) {
+ bin_size =3D (int) &_binary_memdisk_edd_bin_size;
+ memdisk_hook =3D (char *) &_binary_memdisk_edd_bin_start;
+ } else {
+ bin_size =3D (int) &_binary_memdisk_bin_size;
+ memdisk_hook =3D (char *) &_binary_memdisk_bin_start;
+ }
+
/* Reserve the ramdisk memory */
insertrange(ramdisk_image, ramdisk_size, 2, 1);
parse_mem(); /* Recompute variables */
=20
/* Figure out where it needs to go */
- hptr =3D (struct memdisk_header *) &_binary_memdisk_bin_start;
- pptr =3D (struct patch_area *)(_binary_memdisk_bin_start +
hptr->patch_offs);
+ hptr =3D (struct memdisk_header *) memdisk_hook;
+ pptr =3D (struct patch_area *)(memdisk_hook + hptr->patch_offs);
=20
dosmem_k =3D rdz_16(BIOS_BASEMEM);
pptr->olddosmem =3D dosmem_k;
@@ -726,10 +738,6 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void
*cs_bounce)
}
puts(" access to high memory\n");
=20
- /* pptr->maxint13func defaults to EDD enabled, if compiled in */
- if (!do_edd)
- pptr->maxint13func =3D MAXINT13_NOEDD;
-
/* Set up a drive parameter table */
if ( geometry->driveno & 0x80 ) {
/* Hard disk */
@@ -898,7 +906,7 @@ __cdecl void setup(__cdecl syscall_t cs_syscall, void
*cs_bounce)
hptr =3D (struct memdisk_header *)dpp;
=20
/* Actually copy to low memory */
- dpp =3D mempcpy(dpp, &_binary_memdisk_bin_start, bin_size);
+ dpp =3D mempcpy(dpp, memdisk_hook, bin_size);
dpp =3D mempcpy(dpp, ranges, (nranges+1)*sizeof(ranges[0]));
dpp =3D mempcpy(dpp, shdr->cmdline, cmdlinelen+1);
}
--=20
1.5.3.4
------_=_NextPart_001_01C9A06C.565F4677
Content-Type: application/octet-stream;
name="0001-memdisk-varieties-Allow-for-multiple-memdisk-instal.patch"
Content-Transfer-Encoding: base64
Content-Description:
0001-memdisk-varieties-Allow-for-multiple-memdisk-instal.patch
Content-Disposition: attachment;
filename="0001-memdisk-varieties-Allow-for-multiple-memdisk-instal.patch"
RnJvbSBjOGQ3ZjE0YTkzOWMyYWJiNzE2NWVhZmE1NzUyMWFlMjlmYWJlMzI3IE1vbiBTZXAgMTcg
MDA6MDA6MDAgMjAwMQpGcm9tOiBTaGFvIE1pbGxlciA8c2hhby5taWxsZXJAeXJkc2IuZWR1Lm9u
LmNhPgpEYXRlOiBTdW4sIDggTWFyIDIwMDkgMjM6NTQ6NDMgLTA0MDAKU3ViamVjdDogW1BBVENI
XSBtZW1kaXNrIHZhcmlldGllczogQWxsb3cgZm9yIG11bHRpcGxlIG1lbWRpc2sgaW5zdGFsbGFi
bGUgaG9va3MKClRoaXMgcGF0Y2ggInNldHMgdGhlIHN0YWdlIiBmb3IgdGhlIG1lbWRpc2sga2Vy
bmVsIHRvIGluY2x1ZGUgZGlmZmVyZW50CiJpbnN0YWxsYWJsZXMiOiB2ZXJzaW9ucyBvZiB0aGUg
bWVtZGlzayBob29rcy4KClRoaXMgcGF0Y2ggc3BsaXRzIHRoZSBjYXNlIG9mIHRoZSBFREQtY29t
cGlsZWQgaG9vayBmcm9tIHRoZSBub24tRURELWNvbXBpbGVkCmhvb2suICBCb3RoIGFyZSBhdmFp
bGFibGUgaW5zaWRlIHRoZSBrZXJuZWwsIGFuZCB0aGUga2VybmVsIGNob29zZXMgd2hpY2ggb25l
CnRvIGluc3RhbGwgYmFzZWQgb24gdGhlIGNvbW1hbmQtbGluZS4KCkl0J3MgcG9zc2libGUgdGhh
dCBvdGhlciwgc2xpZ2h0bHkgbW9kaWZpZWQgdmVyc2lvbnMgb2YgdGhlIG1lbWRpc2sgaG9vayBj
b3VsZApiZSB1c2VmdWwgdG8gaGF2ZS4uLgotLS0KIG1lbWRpc2svTWFrZWZpbGUgICAgICAgIHwg
ICAgOSArLQogbWVtZGlzay9tZW1kaXNrLmFzbSAgICAgfCAgOTg4ICstLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiBtZW1kaXNrL21lbWRpc2suaW5jICAgICB8
ICA5ODcgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogbWVt
ZGlzay9tZW1kaXNrX2VkZC5hc20gfCAgICAyICsKIG1lbWRpc2svc2V0dXAuYyAgICAgICAgIHwg
ICAyOCArLQogNSBmaWxlcyBjaGFuZ2VkLCAxMDE0IGluc2VydGlvbnMoKyksIDEwMDAgZGVsZXRp
b25zKC0pCiBjcmVhdGUgbW9kZSAxMDA2NDQgbWVtZGlzay9tZW1kaXNrLmluYwogY3JlYXRlIG1v
ZGUgMTAwNjQ0IG1lbWRpc2svbWVtZGlza19lZGQuYXNtCgpkaWZmIC0tZ2l0IGEvbWVtZGlzay9N
YWtlZmlsZSBiL21lbWRpc2svTWFrZWZpbGUKaW5kZXggMzc3NjczMS4uYjhjYjkxYSAxMDA2NDQK
LS0tIGEvbWVtZGlzay9NYWtlZmlsZQorKysgYi9tZW1kaXNrL01ha2VmaWxlCkBAIC0yMCw3ICsy
MCw3IEBAIExERkxBR1MgID0gJChHQ0NPUFQpIC1nCiBJTkNMVURFICA9IC1JJCh0b3BkaXIpL2Nv
bTMyL2luY2x1ZGUKIE5BU00gICAgID0gbmFzbQogTkFTTU9QVCAgPSAtTzk5OTkKLU5GTEFHUyAg
ID0gLWREQVRFPSciJChEQVRFKSInIC1kV0lUSF9FREQKK05GTEFHUyAgID0gLWREQVRFPSciJChE
QVRFKSInCiBOSU5DTFVERSA9CiAKIFNSQ1MJID0gJCh3aWxkY2FyZCAqLmFzbSAqLmMgKi5oKQpA
QCAtMzgsMTEgKzM4LDExIEBAIGVuZGlmCiAjIEltcG9ydGFudDogaW5pdC5vMTYgbXVzdCBiZSBm
aXJzdCEhCiBPQkpTMTYgICA9IGluaXQubzE2IGluaXQzMi5vCiBPQkpTMzIgICA9IHN0YXJ0MzIu
byBzZXR1cC5vIG1zZXR1cC5vIGU4MjBmdW5jLm8gY29uaW8ubyBtZW1jcHkubyBtZW1zZXQubyBc
Ci0gICAgICAgICAgIHVuemlwLm8gbWVtZGlzay5vCisgICAgICAgICAgIHVuemlwLm8gbWVtZGlz
ay5vIG1lbWRpc2tfZWRkLm8KIAogQ1NSQyAgICAgPSBzZXR1cC5jIG1zZXR1cC5jIGU4MjBmdW5j
LmMgY29uaW8uYyB1bnppcC5jCiBTU1JDICAgICA9IHN0YXJ0MzIuUyBtZW1jcHkuUyBtZW1zZXQu
UwotTkFTTVNSQyAgPSBtZW1kaXNrLmFzbSBtZW1kaXNrMTYuYXNtCitOQVNNU1JDICA9IG1lbWRp
c2suYXNtIG1lbWRpc2tfZWRkLmFzbSBtZW1kaXNrMTYuYXNtCiAKIGFsbDogbWVtZGlzayAjIGU4
MjB0ZXN0CiAKQEAgLTExMCw2ICsxMTAsOSBAQCBlODIwdGVzdDogZTgyMHRlc3QuYyBlODIwZnVu
Yy5jIG1zZXR1cC5jCiBtZW1kaXNrLm86IG1lbWRpc2suYmluCiAJJChMRCkgLXIgLWIgYmluYXJ5
IC1vICRAICQ8CiAKK21lbWRpc2tfZWRkLm86IG1lbWRpc2tfZWRkLmJpbgorCSQoTEQpIC1yIC1i
IGJpbmFyeSAtbyAkQCAkPAorCiAuZGVwZW5kOgogCXJtIC1mIC5kZXBlbmQKIAlmb3IgY3NyYyBp
biAqLmMgOyBkbyAkKENDKSAkKElOQ0xVREUpICQoQ0ZMQUdTKSAtTU0gJCRjc3JjID4+IC5kZXBl
bmQgOyBkb25lCmRpZmYgLS1naXQgYS9tZW1kaXNrL21lbWRpc2suYXNtIGIvbWVtZGlzay9tZW1k
aXNrLmFzbQppbmRleCAwZDQ4OTYxLi5kYWE1YzBhIDEwMDY0NAotLS0gYS9tZW1kaXNrL21lbWRp
c2suYXNtCisrKyBiL21lbWRpc2svbWVtZGlzay5hc20KQEAgLTEsOTg3ICsxIEBACi07IC0qLSBm
dW5kYW1lbnRhbCAtKi0gKGFzbS1tb2RlIHN1Y2tzKQotOyAqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi07
Ci07ICBtZW1kaXNrLmFzbQotOwotOyAgQSBwcm9ncmFtIHRvIGVtdWxhdGUgYW4gSU5UIDEzaCBk
aXNrIEJJT1MgZnJvbSBhICJkaXNrIiBpbiBleHRlbmRlZAotOyAgbWVtb3J5LgotOwotOyAgIENv
cHlyaWdodCAyMDAxLTIwMDggSC4gUGV0ZXIgQW52aW4gLSBBbGwgUmlnaHRzIFJlc2VydmVkCi07
Ci07ICBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUg
aXQgYW5kL29yIG1vZGlmeQotOyAgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJh
bCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKLTsgIHRoZSBGcmVlIFNvZnR3YXJlIEZv
dW5kYXRpb24sIEluYy4sIDUzIFRlbXBsZSBQbGFjZSBTdGUgMzMwLAotOyAgQm9zdG9uIE1BIDAy
MTExLTEzMDcsIFVTQTsgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKLTsgIChh
dCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb247IGluY29ycG9yYXRlZCBoZXJlaW4gYnkg
cmVmZXJlbmNlLgotOwotOyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCi0KLSVpZm5kZWYgREVQRU5ECi0l
aW5jbHVkZQkiLi4vdmVyc2lvbi5nZW4iCi0lZW5kaWYKLQotOyAlZGVmaW5lIERFQlVHX1RSQUNF
UlMJCQk7IFVuY29tbWVudCB0byBnZXQgZGVidWdnaW5nIHRyYWNlcnMKLQotJWlmZGVmIFdJVEhf
RURECi0lZGVmaW5lIEVERCAxCi0lZWxzZQotJWRlZmluZSBFREQgMAotJWVuZGlmCi0KLSVpZmRl
ZiBERUJVR19UUkFDRVJTCi0KLSVtYWNybyBUUkFDRVIJMQotCWNhbGwgZGVidWdfdHJhY2VyCi0J
ZGIgJTEKLSVlbmRtYWNybwotCi0lZWxzZQk7IERFQlVHX1RSQUNFUlMKLQotJW1hY3JvCVRSQUNF
UgkxCi0lZW5kbWFjcm8KLQotJWVuZGlmCTsgREVCVUdfVFJBQ0VSUwotCi0lZGVmaW5lIENPTkZJ
R19SRUFET05MWQkweDAxCi0lZGVmaW5lIENPTkZJR19SQVcJMHgwMgotJWRlZmluZSBDT05GSUdf
U0FGRUlOVAkweDA0Ci0lZGVmaW5lIENPTkZJR19CSUdSQVcJMHgwOAkJOyBNVVNUIGJlIDghCi0K
LQkJb3JnIDBoCi0KLSVkZWZpbmUgU0VDVE9SU0laRV9MRzIJOQkJOyBsb2cyKHNlY3RvciBzaXpl
KQotJWRlZmluZQlTRUNUT1JTSVpFCSgxIDw8IFNFQ1RPUlNJWkVfTEcyKQotCi0JCTsgUGFyYW1l
dGVyIHJlZ2lzdGVycyBkZWZpbml0aW9uOyB0aGlzIGlzIHRoZSBkZWZpbml0aW9uCi0JCTsgb2Yg
dGhlIHN0YWNrIGZyYW1lLgotJWRlZmluZQkJUF9EUwkJd29yZCBbYnArMzRdCi0lZGVmaW5lCQlQ
X0VTCQl3b3JkIFticCszMl0KLSVkZWZpbmUJCVBfRUFYCQlkd29yZCBbYnArMjhdCi0lZGVmaW5l
CQlQX0hBWAkJd29yZCBbYnArMzBdCi0lZGVmaW5lCQlQX0FYCQl3b3JkIFticCsyOF0KLSVkZWZp
bmUJCVBfQUwJCWJ5dGUgW2JwKzI4XQotJWRlZmluZQkJUF9BSAkJYnl0ZSBbYnArMjldCi0lZGVm
aW5lCQlQX0VDWAkJZHdvcmQgW2JwKzI0XQotJWRlZmluZQkJUF9IQ1gJCXdvcmQgW2JwKzI2XQot
JWRlZmluZQkJUF9DWAkJd29yZCBbYnArMjRdCi0lZGVmaW5lCQlQX0NMCQlieXRlIFticCsyNF0K
LSVkZWZpbmUJCVBfQ0gJCWJ5dGUgW2JwKzI1XQotJWRlZmluZQkJUF9FRFgJCWR3b3JkIFticCsy
MF0KLSVkZWZpbmUJCVBfSERYCQl3b3JkIFticCsyMl0KLSVkZWZpbmUJCVBfRFgJCXdvcmQgW2Jw
KzIwXQotJWRlZmluZQkJUF9ETAkJYnl0ZSBbYnArMjBdCi0lZGVmaW5lCQlQX0RICQlieXRlIFti
cCsyMV0KLSVkZWZpbmUJCVBfRUJYCQlkd29yZCBbYnArMTZdCi0lZGVmaW5lCQlQX0hCWAkJd29y
ZCBbYnArMThdCi0lZGVmaW5lCQlQX0hCWEwJCWJ5dGUgW2JwKzE4XQotJWRlZmluZQkJUF9CWAkJ
d29yZCBbYnArMTZdCi0lZGVmaW5lCQlQX0JMCQlieXRlIFticCsxNl0KLSVkZWZpbmUJCVBfQkgJ
CWJ5dGUgW2JwKzE3XQotJWRlZmluZQkJUF9FQlAJCWR3b3JkIFticCs4XQotJWRlZmluZQkJUF9C
UAkJd29yZCBbYnArOF0KLSVkZWZpbmUJCVBfRVNJCQlkd29yZCBbYnArNF0KLSVkZWZpbmUJCVBf
U0kJCXdvcmQgW2JwKzRdCi0lZGVmaW5lCQlQX0VESQkJZHdvcmQgW2JwXQotJWRlZmluZQkJUF9E
SQkJd29yZCBbYnBdCi0KLQkJc2VjdGlvbiAudGV4dAotCQk7IFRoZXNlIHBvaW50ZXJzIGFyZSB1
c2VkIGJ5IHRoZSBpbnN0YWxsZXIgYW5kCi0JCTsgbXVzdCBiZSBmaXJzdCBpbiB0aGUgYmluYXJ5
Ci1Qb2ludGVyczoJZHcgSW50MTNTdGFydAotCQlkdyBJbnQxNVN0YXJ0Ci0JCWR3IFBhdGNoQXJl
YQotCQlkdyBUb3RhbFNpemUKLQkJZHcgSXJldFB0cgotCi1JcmV0UHRyCQllcXUgSW50MTNTdGFy
dC5pcmV0Ci1JbnQxM1N0YXJ0OgotCQk7IFN3YXAgc3RhY2sKLQkJbW92IFtjczpTdGFja10sZXNw
Ci0JCW1vdiBbY3M6U2F2ZWRBWF0sYXgKLQkJbW92IGF4LHNzCi0JCW1vdiBbY3M6U3RhY2srNF0s
YXgKLQkJbW92IGF4LGNzCi0JCW1vdiBzcyxheAotCQltb3Ygc3AsW2NzOk15U3RhY2tdCi0KLQkJ
OyBTZWUgaWYgREwgcG9pbnRzIHRvIG91ciBjbGFzcyBvZiBkZXZpY2UgKEZELCBIRCkKLQkJcHVz
aCBkeAotCQlwdXNoIGR4Ci0JCXhvciBkbCxbY3M6RHJpdmVOb10KLQkJcG9wIGR4Ci0JCWpzIC5u
b21hdGNoCQk7IElmIFNGPTAsIHdlIGhhdmUgYSBjbGFzcyBtYXRjaCBoZXJlCi0JCWp6IC5vdXJf
ZHJpdmUJCTsgSWYgWkY9MSwgd2UgaGF2ZSBhbiBleGFjdCBtYXRjaAotCQljbXAgZGwsW2NzOkRy
aXZlTm9dCi0JCWpiIC5ub21hdGNoCQk7IERyaXZlIDwgT3VyIGRyaXZlCi0JCWRlYyBkbAkJCTsg
RHJpdmUgPiBPdXIgZHJpdmUsIGFkanVzdCBkcml2ZSAjCi0ubm9tYXRjaDoKLQkJbW92IGF4LFtj
czpTYXZlZEFYXQotCQlwdXNoZgotCQljYWxsIGZhciBbY3M6T2xkSW50MTNdCi0JCXB1c2hmCi0J
CXB1c2ggYnAKLQkJbW92IGJwLHNwCi0JCWNtcCBieXRlIFtjczpTYXZlZEFYKzFdLDA4aAotCQlq
ZSAubm9yZXN0b3JlZGwKLQkJY21wIGJ5dGUgW2NzOlNhdmVkQVgrMV0sMTVoCi0JCWpuZSAucmVz
dG9yZWRsCi0JCXRlc3QgYnl0ZSBbYnArNF0sODBoCTsgSGFyZCBkaXNrPwotCQlqbnogLm5vcmVz
dG9yZWRsCi0ucmVzdG9yZWRsOgotCQltb3YgZGwsW2JwKzRdCi0ubm9yZXN0b3JlZGw6Ci0JCXB1
c2ggYXgKLQkJcHVzaCBlYngKLQkJcHVzaCBkcwotCQltb3YgYXgsW2JwKzJdCQk7IEZsYWdzCi0J
CWxkcyBlYngsW2NzOlN0YWNrXQotCQltb3YgW2J4KzRdLGFsCQk7IEFyaXRobWV0cmljIGZsYWdz
Ci0JCXBvcCBkcwotCQlwb3AgZWJ4Ci0JCXBvcCBheAotCQlwb3AgYnAKLQkJbHNzIGVzcCxbY3M6
U3RhY2tdCi0uaXJldDoJCWlyZXQKLQotLm91cl9kcml2ZToKLQkJOyBTZXQgdXAgc3RhbmRhcmQg
ZW50cnkgZnJhbWUKLQkJcHVzaCBkcwotCQlwdXNoIGVzCi0JCW1vdiBkcyxheAotCQltb3YgZXMs
YXgKLQkJbW92IGF4LFtTYXZlZEFYXQotCQlwdXNoYWQKLQkJbW92IGJwLHNwCQk7IFBvaW50IEJQ
IHRvIHRoZSBlbnRyeSBzdGFjayBmcmFtZQotCQlUUkFDRVIgJ0YnCi0JCTsgTm90ZTogQUggPT0g
UF9BSCBoZXJlCi0JCWNtcCBhaCxbSW50MTNNYXhGdW5jXQotCQlqYSBJbnZhbGlkX2p1bXAKLQkJ
eG9yIGFsLGFsCQk7IEFMID0gMCBpcyBzdGFuZGFyZCBlbnRyeSBjb25kaXRpb24KLQkJbW92IGRp
LGF4Ci0JCXNociBkaSw3CQk7IENvbnZlcnQgQUggdG8gYW4gb2Zmc2V0IGluIERJCi0JCWNhbGwg
W0ludDEzRnVuY3MrZGldCi0KLURvbmU6CQk7IFN0YW5kYXJkIHJvdXRpbmUgZm9yIHJldHVybgot
CQltb3YgUF9BWCxheAotRG9uZVdlaXJkOgotCQlUUkFDRVIgJ0QnCi0JCXhvciBieCxieAotCQlt
b3YgZXMsYngKLQkJbW92IGJ4LFtTdGF0dXNQdHJdCi0JCW1vdiBbZXM6YnhdLGFoCQk7IFNhdmUg
c3RhdHVzCi0JCWFuZCBhaCxhaAotCi0JCWxkcyBlYngsW1N0YWNrXQotCQk7IFRoaXMgc2V0cyB0
aGUgbG93IGJ5dGUgKHRoZSBhcml0aG1ldHJpYyBmbGFncykgb2YgdGhlCi0JCTsgRkxBR1Mgb24g
c3RhY2sgdG8gZWl0aGVyIDAwaCAobm8gZmxhZ3MpIG9yIDAxaCAoQ0YpCi0JCTsgZGVwZW5kaW5n
IG9uIGlmIEFIIHdhcyB6ZXJvIG9yIG5vdC4KLQkJc2V0bnogW2J4KzRdCQk7IFNldCBDRiBpZmYg
ZXJyb3IKLQkJcG9wYWQKLQkJcG9wIGVzCi0JCXBvcCBkcwotCQlsc3MgZXNwLFtjczpTdGFja10K
LQkJaXJldAotCi1SZXNldDoKLQkJOyBSZXNldCBhZmZlY3RzIG11bHRpcGxlIGRyaXZlcywgc28g
d2UgbmVlZCB0byBwYXNzIGl0IG9uCi0JCVRSQUNFUiAnUicKLQkJeG9yIGF4LGF4CQk7IEJvdHRv
bSBvZiBtZW1vcnkKLQkJbW92IGVzLGF4Ci0JCXRlc3QgZGwsZGwJCTsgQWx3YXlzIHBhc3MgaXQg
b24gaWYgd2UgYXJlIHJlc2V0dGluZyBIRAotCQlqcyAuaGFyZF9kaXNrCQk7IEJpdCA3IHNldAot
CQk7IFNvbWUgQklPU2VzIGdldCB2ZXJ5IHVuaGFwcHkgaWYgd2UgcGFzcyBhIHJlc2V0IGZsb3Bw
eQotCQk7IGNvbW1hbmQgdG8gdGhlbSBhbmQgZG9uJ3QgYWN0dWFsbHkgaGF2ZSBhbnkgZmxvcHBp
ZXMuCi0JCTsgVGhpcyBpcyBhIGJ1ZywgYnV0IHdlIGhhdmUgdG8gZGVhbCB3aXRoIGl0IG5vbnRo
ZWxlc3MuCi0JCTsgVGhlcmVmb3JlLCBpZiB3ZSBhcmUgdGhlICpPTkxZKiBmbG9wcHkgZHJpdmUs
IGFuZCB0aGUKLQkJOyB1c2VyIGRpZG4ndCByZXF1ZXN0IEhEIHJlc2V0LCB0aGVuIGp1c3QgZHJv
cCB0aGUgY29tbWFuZC4KLQkJOyBCSU9TIGVxdWlwbWVudCBieXRlLCB0b3AgdHdvIGJpdHMgKyAx
ID09IHRvdGFsICMgb2YgZmxvcHBpZXMKLQkJdGVzdCBieXRlIFtlczoweDQxMF0sMEMwaAotCQlq
eiBzdWNjZXNzCi0JCWptcCAucGFzc19vbgkJOyAuLi4gb3RoZXJ3aXNlIHBhc3MgaXQgdG8gdGhl
IEJJT1MKLS5oYXJkX2Rpc2s6Ci0JCTsgLi4uIHNhbWUgdGhpbmcgZm9yIGhhcmQgZGlza3MsIHNp
Z2ggLi4uCi0JCWNtcCBieXRlIFtlczoweDQ3NV0sMQk7IEJJT1MgdmFyaWFibGUgZm9yIG51bWJl
ciBvZiBoYXJkIGRpc2tzCi0JCWpiZSBzdWNjZXNzCi0KLS5wYXNzX29uOgotCQlwb3AgYXgJCQk7
IERyb3AgcmV0dXJuIGFkZHJlc3MKLQkJcG9wYWQJCQk7IFJlc3RvcmUgYWxsIHJlZ2lzdGVycwot
CQlwb3AgZXMKLQkJcG9wIGRzCi0JCWxzcyBlc3AsW2NzOlN0YWNrXQk7IFJlc3RvcmUgdGhlIHN0
YWNrCi0JCWFuZCBkbCw4MGgJCTsgQ2xlYXIgYWxsIGJ1dCB0aGUgdHlwZSBiaXQKLQkJam1wIGZh
ciBbY3M6T2xkSW50MTNdCi0KLQotSW52YWxpZDoKLQkJcG9wIGR4CQkJOyBEcm9wIHJldHVybiBh
ZGRyZXNzCi1JbnZhbGlkX2p1bXA6Ci0JCVRSQUNFUiAnSScKLQkJbW92IGFoLDAxaAkJOyBVbnN1
cHBvcnRlZCBmdW5jdGlvbgotCQlqbXAgc2hvcnQgRG9uZQotCi1HZXREcml2ZVR5cGU6Ci0JCXRl
c3QgYnl0ZSBbRHJpdmVOb10sODBoCi0JCW1vdiBibCwwMmgJCTsgVHlwZSAwMmggPSBmbG9wcHkg
d2l0aCBjaGFuZ2VsaW5lCi0JCWp6IC5mbG9wcHkKLQkJOyBIYXJkIGRpc2tzIG9ubHkuLi4KLQkJ
aW5jIGJ4CQkJOyBUeXBlID0gMDNoCi0JCW1vdiBkeCxbRGlza1NpemVdCTsgUmV0dXJuIHRoZSBk
aXNrIHNpemUgaW4gc2VjdG9ycwotCQltb3YgUF9EWCxkeAotCQltb3YgY3gsW0Rpc2tTaXplKzJd
Ci0JCW1vdiBQX0NYLGN4Ci0uZmxvcHB5OgotCQltb3YgUF9BSCxibAkJOyAwMmggZmxvcHB5LCAw
M2ggaGFyZCBkaXNrCi0JCXBvcCBheAkJCTsgRHJvcCByZXR1cm4gYWRkcmVzcwotCQl4b3IgYXgs
YXgJCTsgU3VjY2Vzcy4uLgotCQlqbXAgRG9uZVdlaXJkCQk7IEJ1dCBkb24ndCBzdGljayBpdCBp
bnRvIFBfQVgKLQotR2V0U3RhdHVzOgotCQl4b3IgYXgsYXgKLQkJbW92IGVzLGF4Ci0JCW1vdiBi
eCxbU3RhdHVzUHRyXQotCQltb3YgYWgsW2J4XQkJOyBDb3B5IGxhc3Qgc3RhdHVzCi0JCXJldAot
Ci1SZWFkTXVsdDoKLQkJVFJBQ0VSICdtJwotUmVhZDoKLQkJVFJBQ0VSICdSJwotCQljYWxsIHNl
dHVwX3JlZ3MKLWRvX2NvcHk6Ci0JCVRSQUNFUiAnPCcKLQkJY2FsbCBiY29weQotCQlUUkFDRVIg
Jz4nCi0JCW1vdnp4IGF4LFBfQUwJCTsgQUggPSAwLCBBTCA9IHRyYW5zZmVyIGNvdW50Ci0JCXJl
dAotCi1Xcml0ZU11bHQ6Ci0JCVRSQUNFUiAnTScKLVdyaXRlOgotCQlUUkFDRVIgJ1cnCi0JCXRl
c3QgYnl0ZSBbQ29uZmlnRmxhZ3NdLENPTkZJR19SRUFET05MWQotCQlqbnogLnJlYWRvbmx5Ci0J
CWNhbGwgc2V0dXBfcmVncwotCQl4Y2hnIGVzaSxlZGkJCTsgT3Bwb3NpdGUgZGlyZWN0aW9uIG9m
IGEgUmVhZCEKLQkJam1wIHNob3J0IGRvX2NvcHkKLS5yZWFkb25seToJbW92IGFoLDAzaAkJOyBX
cml0ZSBwcm90ZWN0ZWQgbWVkaXVtCi0JCXJldAotCi0JCTsgVmVyaWZ5IGludGVncml0eTsganVz
dCBib3VuZHMtY2hlY2sKLVNlZWs6Ci1WZXJpZnk6Ci0JCWNhbGwgc2V0dXBfcmVncwkJOyBSZXR1
cm5zIGVycm9yIGlmIGFwcHJvcHJpYXRlCi0JCTsgQW5kIGZhbGwgdGhyb3VnaCB0byBzdWNjZXNz
Ci0KLUNoZWNrSWZSZWFkeToJCQkJOyBUaGVzZSBhcmUgYWx3YXlzLXN1Y2Nlc3NmdWwgbm9vcCBm
dW5jdGlvbnMKLVJlY2FsaWJyYXRlOgotSW5pdFdpdGhQYXJtczoKLURldGVjdENoYW5nZToKLUVE
RERldGVjdENoYW5nZToKLUVERExvY2s6Ci1TZXRNb2RlOgotc3VjY2VzczoKLQkJeG9yIGF4LGF4
CQk7IEFsd2F5cyBzdWNjZXNzZnVsCi0JCXJldAotCi1HZXRQYXJtczoKLQkJVFJBQ0VSICdHJwot
CQltb3YgZGwsW0RyaXZlQ250XQk7IENhY2hlZCBkYXRhCi0JCW1vdiBQX0RMLGRsCi0JCXRlc3Qg
Ynl0ZSBbRHJpdmVOb10sODBoCi0JCWpueiAuaGQKLQkJbW92IFBfREksRFBUCi0JCW1vdiBQX0VT
LGNzCi0JCW1vdiBibCxbRHJpdmVUeXBlXQotCQltb3YgUF9CTCxibAotLmhkOgotCQltb3YgYXgs
W0N5bGluZGVyc10KLQkJZGVjIGF4CQkJOyBXZSByZXBvcnQgdGhlIGhpZ2hlc3QgIywgbm90IHRo
ZSBjb3VudAotCQl4Y2hnIGFsLGFoCi0JCXNobCBhbCw2Ci0JCW9yIGFsLFtTZWN0b3JzXQotCQlt
b3YgUF9DWCxheAotCQltb3YgYXgsW0hlYWRzXQotCQlkZWMgYXgKLQkJbW92IFBfREgsYWwKLQot
CQk7Ci0JCTsgSXMgdGhpcyBNRU1ESVNLIGluc3RhbGxhdGlvbiBjaGVjaz8KLQkJOwotCQljbXAg
UF9IQVgsJ01FJwotCQlqbmUgLm5vdGljCi0JCWNtcCBQX0hDWCwnTUQnCi0JCWpuZSAubm90aWMK
LQkJY21wIFBfSERYLCdJUycKLQkJam5lIC5ub3RpYwotCQljbXAgUF9IQlgsJ0s/JwotCQlqbmUg
Lm5vdGljCi0KLQkJOyBNRU1ESVNLIGluc3RhbGxhdGlvbiBjaGVjay4uLgotCQltb3YgUF9IQVgs
JyFNJwotCQltb3YgUF9IQ1gsJ0VNJwotCQltb3YgUF9IRFgsJ0RJJwotCQltb3YgUF9IQlgsJ1NL
JwotCQltb3YgUF9FUyxjcwotCQltb3YgUF9ESSxNZW1EaXNrX0luZm8KLQotLm5vdGljOgotCQl4
b3IgYXgsYXgKLQkJcmV0Ci07Ci07IEVERCBmdW5jdGlvbnMgLS0gb25seSBpZiBlbmFibGVkCi07
Ci0laWYgRURECi1FRERQcmVzZW5jZToKLQkJVFJBQ0VSICdFJwotCQlUUkFDRVIgJ2MnCi0KLQkJ
Y21wIFBfQlgsNTVBQWgKLQkJam5lIEludmFsaWQKLQkJbW92IFBfQlgsMEFBNTVoCQk7IEVERCBz
aWduYXR1cmUKLQkJbW92IFBfQVgsMDMwMDBoCQk7IEVERCAzLjAKLQkJbW92IFBfQ1gsMDAwM2gJ
CTsgQml0IDAgLSBGaXhlZCBkaXNrIGFjY2VzcyBzdWJzZXQKLQkJCQkJOyBCaXQgMSAtIExvY2tp
bmcgYW5kIGVqZWN0aW5nIHN1YnNldAotCQlwb3AgYXgJCQk7IERyb3AgcmV0dXJuIGFkZHJlc3MK
LQkJeG9yIGF4LGF4CQk7IFN1Y2Nlc3MKLQkJam1wIERvbmVXZWlyZAkJOyBTdWNjZXNzLCBidXQg
QUggIT0gMCwgc2lnaC4uLgotCi1FRERSZWFkOgotCQlUUkFDRVIgJ0UnCi0JCVRSQUNFUiAncicK
LQotCQljYWxsIGVkZF9zZXR1cF9yZWdzCi0JCWNhbGwgYmNvcHkKLQkJeG9yIGF4LGF4Ci0JCXJl
dAotCi1FRERXcml0ZToKLQkJVFJBQ0VSICdFJwotCQlUUkFDRVIgJ3cnCi0KLQkJY2FsbCBlZGRf
c2V0dXBfcmVncwotCQl4Y2hnIGVzaSxlZGkKLQkJY2FsbCBiY29weQotCQl4b3IgYXgsYXgKLQkJ
cmV0Ci0KLUVERFZlcmlmeToKLUVERFNlZWs6Ci0JCWNhbGwgZWRkX3NldHVwX3JlZ3MJOyBKdXN0
IGJvdW5kcyBjaGVja2luZwotCQl4b3IgYXgsYXgKLQkJcmV0Ci0KLUVEREdldFBhcm1zOgotCQlU
UkFDRVIgJ0UnCi0JCVRSQUNFUiAncCcKLQotCQltb3YgZXMsUF9EUwotCQltb3YgZGksUF9TSQot
CQltb3Ygc2ksRUREX0RQVAotCi0JCWxvZHN3CQkJOyBMZW5ndGggb2Ygb3VyIERQVAotCQltb3Yg
Y3gsW2VzOmRpXQotCQljbXAgY3gsMjYJCTsgTWluaW11bSBzaXplCi0JCWpiIC5vdmVycnVuCi0K
LQkJY21wIGN4LGF4Ci0JCWpiIC5va3NpemUKLQkJbW92IGN4LGF4Ci0KLS5va3NpemU6Ci0JCW1v
diBheCxjeAotCQlzdG9zdwotCQlkZWMgY3gKLQkJZGVjIGN4Ci0JCXJlcCBtb3ZzYgotCi0JCXhv
ciBheCxheAotCQlyZXQKLQotLm92ZXJydW46Ci0JCW1vdiBheCwwMTAwaAotCQlyZXQKLSVlbmRp
ZiA7IEVERAotCi0JCTsgU2V0IHVwIHJlZ2lzdGVycyBhcyBmb3IgYSAiUmVhZCIsIGFuZCBjb21w
YXJlcyBhZ2FpbnN0IGRpc2sgc2l6ZS4KLQkJOyBXQVJOSU5HOiBUaGlzIGZhaWxzIGltbWVkaWF0
ZWx5LCBldmVuIGlmIHdlIGNhbiB0cmFuc2ZlciBzb21lCi0JCTsgc2VjdG9ycy4gIFRoaXMgaXNu
J3QgcmVhbGx5IHRoZSBjb3JyZWN0IGJlaGF2aW91ci4KLXNldHVwX3JlZ3M6Ci0KLQkJOyBDb252
ZXJ0IGEgQ0hTIGFkZHJlc3MgaW4gUF9DWC9QX0RIIGludG8gYW4gTEJBIGluIGVheAotCQk7IENI
ID0gY3lsWzc6MF0KLQkJOyBDTFswOjVdID0gc2VjdG9yICgxLWJhc2VkKSAgQ0xbNzo2XSA9IGN5
bFs5OjhdCi0JCTsgREggPSBoZWFkCi0JCW1vdnp4IGVjeCxQX0NYCi0JCW1vdnp4IGVieCxjbAkJ
OyBTZWN0b3IgbnVtYmVyCi0JCWFuZCBibCwzRmgKLQkJZGVjIGVieAkJCTsgU2VjdG9yIG51bWJl
ciBpcyAxLWJhc2VkCi0JCWNtcCBieCxbU2VjdG9yc10KLQkJamFlIC5vdmVycnVuCi0JCW1vdnp4
IGVkaSxQX0RICQk7IEhlYWQgbnVtYmVyCi0JCW1vdnp4IGVheCx3b3JkIFtIZWFkc10KLQkJY21w
IGRpLGF4Ci0JCWphZSAub3ZlcnJ1bgotCQlzaHIgY2wsNgotCQl4Y2hnIGNsLGNoCQk7IE5vdyAo
RSlDWCA8LSBjeWxpbmRlciBudW1iZXIKLQkJbXVsIGVjeAkJCTsgZWF4IDwtIEhlYWRzKmN5bCMg
KGVkeCA8LSAwKQotCQlhZGQgZWF4LGVkaQotCQltdWwgZHdvcmQgW1NlY3RvcnNdCi0JCWFkZCBl
YXgsZWJ4Ci0JCTsgTm93IGVheCA9IExCQSwgZWR4ID0gMAotCi0JCTsKLQkJOyBzZXR1cF9yZWdz
IGNvbnRpbnVlcy4uLgotCQk7Ci0JCTsgTm90ZTogZWRpWzMxOjE2XSBhbmQgZWN4WzMxOjE2XSA9
IDAgYWxyZWFkeQotCQltb3YgZGksUF9CWAkJOyBHZXQgbGluZWFyIGFkZHJlc3Mgb2YgdGFyZ2V0
IGJ1ZmZlcgotCQltb3YgY3gsUF9FUwotCQlzaGwgZWN4LDQKLQkJYWRkIGVkaSxlY3gJCTsgRURJ
ID0gYWRkcmVzcyB0byBmZXRjaCB0bwotCQltb3Z6eCBlY3gsUF9BTAkJOyBTZWN0b3IgY291bnQK
LQkJbW92IGVzaSxlYXgKLQkJYWRkIGVheCxlY3gJCTsgTEJBIG9mIGZpbmFsIHNlY3RvciArIDEK
LQkJc2hsIGVzaSxTRUNUT1JTSVpFX0xHMgk7IExCQSAtPiBieXRlIG9mZnNldAotCQlhZGQgZXNp
LFtEaXNrQnVmXQk7IEdldCBhZGRyZXNzIGluIGhpZ2ggbWVtb3J5Ci0JCWNtcCBlYXgsW0Rpc2tT
aXplXQk7IENoZWNrIHRoZSBoaWdoIG1hcmsgYWdhaW5zdCBsaW1pdAotCQlqYSAub3ZlcnJ1bgot
CQlzaGwgZWN4LFNFQ1RPUlNJWkVfTEcyLTIgOyBDb252ZXJ0IGNvdW50IHRvIGR3b3JkcwotCQly
ZXQKLQotLm92ZXJydW46CXBvcCBheAkJCTsgRHJvcCBzZXR1cF9yZWdzIHJldHVybiBhZGRyZXNz
Ci0JCW1vdiBheCwwMjAwaAkJOyBNaXNzaW5nIGFkZHJlc3MgbWFyawotCQlyZXQJCQk7IFJldHVy
biB0byBEb25lCi0KLQkJOyBTZXQgdXAgcmVnaXN0ZXJzIGFzIGZvciBhbiBFREQgUmVhZCwgYW5k
IGNvbXBhcmVzIGFnYWluc3QgZGlzayBzaXplLgotJWlmIEVERAotZWRkX3NldHVwX3JlZ3M6Ci0J
CXB1c2ggZXMKLQkJbW92IHNpLFBfU0kJCTsgRFM6U0kgLT4gREFQQQotCQltb3YgZXMsUF9EUwot
Ci0JCW1vdiBkeCxbZXM6c2ldCi0JCWNtcCBkeCwxNgotCQlqYiAuYmFkZGFwYQotCi0JCWNtcCBk
d29yZCBbZXM6c2krNF0sLTEKLQkJamUgLmxpbmVhcl9hZGRyZXNzCi0KLQkJbW92enggZWJ4LHdv
cmQgW2VzOnNpKzRdCTsgT2Zmc2V0Ci0JCW1vdnp4IGVkaSx3b3JkIFtlczpzaSs2XQk7IFNlZ21l
bnQKLQkJc2hsIGVkaSw0Ci0JCWFkZCBlYngsZWRpCi0JCWptcCAuZ290X2FkZHJlc3MKLQotLmxp
bmVhcl9hZGRyZXNzOgotCQljbXAgZHgsMjQJCTsgTXVzdCBiZSBsYXJnZSBlbm91Z2ggdG8gaG9s
ZAotCQkJCQk7IGxpbmVhciBhZGRyZXNzCi0JCWpiIC5iYWRkYXBhCi0KLQkJY21wIGR3b3JkIFtl
czpzaSsyMF0sMAk7ID4gNCBHQiBhZGRyZXNzZXMgbm90IHN1cHBvcnRlZAotCQltb3YgYXgsMDkw
MGgJCTsgIkRhdGEgYm91bmRhcnkgZXJyb3IiIC0gYm9ndXMsIGJ1dAotCQkJCQk7IG5vIHJlYWxs
eSBiZXR0ZXIgY29kZSBhdmFpbGFibGUKLQkJam5lIC5lcnJvcgotCi0JCW1vdiBlYngsW2VzOnNp
KzE2XQotCi0uZ290X2FkZHJlc3M6Ci0JCWNtcCBkd29yZCBbZXM6c2krMTJdLDAJCTsgTEJBIHRv
byBsYXJnZT8KLQkJam5lIC5vdmVycnVuCi0KLQkJbW92enggZWN4LCB3b3JkIFtlczpzaSsyXQk7
IFNlY3RvcnMgdG8gdHJhbnNmZXIKLQkJbW92IGVzaSxbZXM6c2krOF0JCTsgU3RhcnRpbmcgc2Vj
dG9yCi0JCW1vdiBlYXgsZXNpCi0JCWFkZCBlYXgsZWN4Ci0JCWpjIC5vdmVycnVuCi0JCWNtcCBl
YXgsW0Rpc2tTaXplXQotCQlqYSAub3ZlcnJ1bgotCi0JCXNobCBlY3gsU0VDVE9SU0laRV9MRzIt
Mgk7IENvbnZlcnQgdG8gZHdvcmRzCi0JCXNobCBlc2ksU0VDVE9SU0laRV9MRzIJCTsgQ29udmVy
dCB0byBhbiBvZmZzZXQKLQkJYWRkIGVzaSxbRGlza0J1Zl0KLQkJbW92IGVkaSxlYngKLQkJcG9w
IGVzCi0JCXJldAotCi0uYmFkZGFwYToKLQkJbW92IGF4LDAxMDBoCQk7IEludmFsaWQgY29tbWFu
ZAotCQlwb3AgZXMKLQkJcG9wIGF4CQkJOyBEcm9wIHNldHVwX3JlZ3MgcmV0dXJuIGFkZHJlc3MK
LQkJcmV0Ci0KLS5vdmVycnVuOgotCQltb3YgYXgsMDIwMGgJCTsgIkFkZHJlc3MgbWFyayBub3Qg
Zm91bmQiID0KLQkJCQkJOyBMQkEgYmV5b25kIGVuZCBvZiBkaXNrCi0uZXJyb3I6Ci0JCWFuZCB3
b3JkIFtlczpzaSsyXSwwCTsgTm8gc2VjdG9ycyB0cmFuc2ZlcnJlZAotCQlwb3AgZXMKLQkJcG9w
IGF4Ci0JCXJldAotCi1FRERFamVjdDoKLQkJbW92IGF4LDBCMjAwaAkJOyBWb2x1bWUgTm90IFJl
bW92YWJsZQotCQlyZXQKLQotJWVuZGlmIDsgRURECi0KLQotOwotOyBJTlQgMTVoIGludGVyY2Vw
dCByb3V0aW5lcwotOwotaW50MTVfZTgyMDoKLQkJY21wIGVkeCw1MzRENDE1MGgJOyAiU01BUCIK
LQkJam5lIG9sZGludDE1Ci0JCWNtcCBlY3gsMjAJCTsgTmVlZCAyMCBieXRlcwotCQlqYiBlcnI4
NgotCQlwdXNoIGRzCi0JCXB1c2ggY3MKLQkJcG9wIGRzCi0JCXB1c2ggZWR4CQk7ICJTTUFQIgot
CQlhbmQgZWJ4LGVieAotCQlqbmUgLnJlbmV3Ci0JCW1vdiBlYngsRTgyMFRhYmxlCi0ucmVuZXc6
Ci0JCWFkZCBieCwxNgkJOyBBZHZhbmNlIHRvIG5leHQKLQkJbW92IGVheCxbYngtOF0JCTsgVHlw
ZQotCQlhbmQgZWF4LGVheAkJOyBOdWxsIHR5cGU/Ci0JCWp6IC5yZW5ldwkJOyBJZiBzbyBhZHZh
bmNlIHRvIG5leHQKLQkJbW92IFtlczpkaSsxNl0sZWF4Ci0JCWFuZCBjbCx+MwotCQljbXAgZWN4
LDI0Ci0JCWpiIC5ub19leHRhdHRyCi0JCW1vdiBlYXgsW2J4LTRdCQk7IEV4dGVuZGVkIGF0dHJp
YnV0ZXMKLQkJbW92IFtlczpkaSsyMF0sZWF4Ci0JCW1vdiBlY3gsMjQJCTsgQnl0ZXMgbG9hZGVk
Ci0ubm9fZXh0YXR0cjoKLQkJbW92IGVheCxbYngtMTZdCQk7IFN0YXJ0IGFkZHIgKGxvdykKLQkJ
bW92IGVkeCxbYngtMTJdCQk7IFN0YXJ0IGFkZHIgKGhpZ2gpCi0JCW1vdiBbZXM6ZGldLGVheAot
CQltb3YgW2VzOmRpKzRdLGVkeAotCQltb3YgZWF4LFtieF0JCTsgRW5kIGFkZHIgKGxvdykKLQkJ
bW92IGVkeCxbYngrNF0JCTsgRW5kIGFkZHIgKGhpZ2gpCi0JCXN1YiBlYXgsW2J4LTE2XQkJOyBE
ZXJpdmUgdGhlIGxlbmd0aAotCQlzYmIgZWR4LFtieC0xMl0KLQkJbW92IFtlczpkaSs4XSxlYXgJ
OyBMZW5ndGggKGxvdykKLQkJbW92IFtlczpkaSsxMl0sZWR4CTsgTGVuZ3RoIChoaWdoKQotCQlj
bXAgZHdvcmQgW2J4KzhdLC0xCTsgVHlwZSBvZiBuZXh0ID0gZW5kPwotCQlqbmUgLm5vdGRvbmUK
LQkJeG9yIGVieCxlYngJCTsgRG9uZSB3aXRoIHRhYmxlCi0ubm90ZG9uZToKLQkJcG9wIGVheAkJ
CTsgIlNNQVAiCi0JCW1vdiBlZHgsZWF4CQk7IFNvbWUgc3lzdGVtcyBleHBlY3QgZWF4ID0gZWR4
ID0gU01BUAotCQlwb3AgZHMKLWludDE1X3N1Y2Nlc3M6Ci0JCW1vdiBieXRlIFticCs2XSwgMDJo
CTsgQ2xlYXIgQ0YKLQkJcG9wIGJwCi0JCWlyZXQKLQotZXJyODY6Ci0JCW1vdiBieXRlIFticCs2
XSwgMDNoCTsgU2V0IENGCi0JCW1vdiBhaCw4NmgKLQkJcG9wIGJwCi0JCWlyZXQKLQotSW50MTVT
dGFydDoKLQkJcHVzaCBicAotCQltb3YgYnAsc3AKLQkJY21wIGF4LDBFODIwaAotCQlqZSBuZWFy
IGludDE1X2U4MjAKLQkJY21wIGF4LDBFODAxaAotCQlqZSBpbnQxNV9lODAxCi0JCWNtcCBheCww
RTg4MWgKLQkJamUgaW50MTVfZTg4MQotCQljbXAgYWgsODhoCi0JCWplIGludDE1Xzg4Ci1vbGRp
bnQxNToJcG9wIGJwCi0JCWptcCBmYXIgW2NzOk9sZEludDE1XQotCi1pbnQxNV9lODAxOgotCQlt
b3YgYXgsW2NzOk1lbTFNQl0KLQkJbW92IGN4LGF4Ci0JCW1vdiBieCxbY3M6TWVtMTZNQl0KLQkJ
bW92IGR4LGJ4Ci0JCWptcCBzaG9ydCBpbnQxNV9zdWNjZXNzCi0KLWludDE1X2U4ODE6Ci0JCW1v
diBlYXgsW2NzOk1lbTFNQl0KLQkJbW92IGVjeCxlYXgKLQkJbW92IGVieCxbY3M6TWVtMTZNQl0K
LQkJbW92IGVkeCxlYngKLQkJam1wIHNob3J0IGludDE1X3N1Y2Nlc3MKLQotaW50MTVfODg6Ci0J
CW1vdiBheCxbY3M6TWVtSW50MTU4OF0KLQkJam1wIHNob3J0IGludDE1X3N1Y2Nlc3MKLQotOwot
OyBSb3V0aW5lIHRvIGNvcHkgaW4vb3V0IG9mIGhpZ2ggbWVtb3J5Ci07IGVzaSA9IGxpbmVhciBz
b3VyY2UgYWRkcmVzcwotOyBlZGkgPSBsaW5lYXIgdGFyZ2V0IGFkZHJlc3MKLTsgZWN4ID0gMzIt
Yml0IHdvcmQgY291bnQKLTsKLTsgQXNzdW1lcyBjcyA9IGRzID0gZXMKLTsKLWJjb3B5OgotCQlw
dXNoIGVheAotCQlwdXNoIGVieAotCQlwdXNoIGVkeAotCQlwdXNoIGVicAotCi0JCW1vdiBieCwg
cmVhbF9pbnQxNV9zdHViCi0KLQkJdGVzdCBieXRlIFtDb25maWdGbGFnc10sIENPTkZJR19SQVd8
Q09ORklHX1NBRkVJTlQKLQkJanogLmFueW1vZGUJCTsgQWx3YXlzIGRvIHRoZSByZWFsIElOVCAx
NWgKLQotCQlzbXN3IGF4CQkJOyBVbnByaXZpbGVnZWQhCi0JCXRlc3QgYWwsMDFoCi0JCWpueiAu
cHJvdG1vZGUJCTsgUHJvdG1vZGUgLT4gZG8gcmVhbCBJTlQgMTVoCi0KLS5yZWFsbW9kZToKLQkJ
OyBSYXcgb3IgU2FmZWludCBtb2RlLCBhbmQgd2UncmUgaW4gcmVhbCBtb2RlLi4uCi0KLQkJdGVz
dCBieXRlIFtDb25maWdGbGFnc10sIENPTkZJR19TQUZFSU5UCi0JCWpueiAuZmFrZWludDE1Ci0K
LS5yYXc6Ci0JCVRSQUNFUiAncicKLQkJOyBXZSdyZSBpbiByZWFsIG1vZGUsIGRvIGl0IG91dHNl
bHZlcwotCi0JCXB1c2hmZAkJCTsgPEE+Ci0JCXB1c2ggZHMJCQk7IDxCPgotCQlwdXNoIGVzCQkJ
OyA8Qz4KLQotCQljbGkKLQkJY2xkCi0KLQkJeG9yIGVieCxlYngKLQkJbW92IGJ4LGNzCi0JCXNo
bCBlYngsNAotCQlsZWEgZWR4LFtTaGFrZXIrZWJ4XQotCQltb3YgW1NoYWtlcisyXSxlZHgKLQot
CQk7IFRlc3QgdG8gc2VlIGlmIEEyMCBpcyBlbmFibGVkIG9yIG5vdAotCQl4b3IgYXgsYXgKLQkJ
bW92IGRzLGF4Ci0JCWRlYyBheAotCQltb3YgZXMsYXgKLQotCQltb3YgYXgsWzBdCi0JCW1vdiBi
eCxheAotCQl4b3IgYngsW2VzOjEwaF0KLQkJbm90IGF4Ci0JCW1vdiBbMF0sYXgKLQkJbW92IGR4
LGF4Ci0JCXhvciBkeCxbZXM6MTBoXQotCQlub3QgYXgKLQkJbW92IFswXSxheAotCi0JCW9yIGR4
LGJ4Ci0JCXB1c2ggZHgJCQk7IDxEPiBTYXZlIEEyMCBzdGF0dXMKLQkJam56IC5za2lwX2EyMGUK
LQotCQltb3YgYXgsMjQwMWgJCTsgRW5hYmxlIEEyMAotCQlpbnQgMTVoCi0uc2tpcF9hMjBlOgot
CQltb3YgZGwsW0NvbmZpZ0ZsYWdzXQotCQlhbmQgZHgsQ09ORklHX0JJR1JBVwotCQlhZGQgZHgs
OAotCQk7IERYID0gMTYgZm9yIEJJR1JBVywgOCBmb3IgUkFXCi0JCTsgIDggaXMgc2VsZWN0b3Ig
Zm9yIGEgNjRLIGZsYXQgc2VnbWVudCwKLQkJOyAxNiBpcyBzZWxlY3RvciBmb3IgYSA0R0IgZmxh
dCBzZWdtZW50LgotCi0JCWxnZHQgW2NzOlNoYWtlcl0KLQkJbW92IGVheCxjcjAKLQkJb3IgYWws
MDFoCi0JCW1vdiBjcjAsZWF4Ci0KLQkJbW92IGJ4LDE2CQk7IExhcmdlIGZsYXQgc2VnbWVudAot
CQltb3YgZHMsYngKLQkJbW92IGVzLGJ4Ci0KLQkJYTMyIHJlcCBtb3ZzZAotCi0JCTsgRFggaGFz
IHRoZSBhcHByb3ByaWF0ZSB2YWx1ZSB0byBwdXQgaW4KLQkJOyB0aGUgcmVnaXN0ZXJzIG9uIHJl
dHVybgotCQltb3YgZHMsZHgKLQkJbW92IGVzLGR4Ci0KLQkJYW5kIGFsLH4wMWgKLQkJbW92IGNy
MCxlYXgKLQotCQlwb3AgZHgJCQk7IDxEPiBBMjAgc3RhdHVzCi0JCXBvcCBlcwkJCTsgPEM+Ci0J
CXBvcCBkcwkJCTsgPEI+Ci0KLQkJYW5kIGR4LGR4Ci0JCWpueiAuc2tpcF9hMjBkCi0JCW1vdiBh
eCwyNDAwaAkJOyBEaXNhYmxlIEEyMAotCQlpbnQgMTVoCi0uc2tpcF9hMjBkOgotCQlwb3BmZAkJ
CTsgPEE+Ci0JCWptcCAuZG9uZQotCi0uZmFrZWludDE1OgotCQk7IFdlJ3JlIGluIHJlYWwgbW9k
ZSB3aXRoIENPTkZJR19TQUZFSU5ULCBpbnZva2UgdGhlCi0JCTsgb3JpZ2luYWwgSU5UIDE1aCB2
ZWN0b3IuICBXZSB1c2VkIHRvIHRlc3QgZm9yIHRoZQotCQk7IElOVCAxNWggdmVjdG9yIGJlaW5n
IHVuY2hhbmdlZCBoZXJlLCBidXQgdGhhdCBpcwotCQk7ICp1cyo7IGhvd2V2ZXIsIHRoZSB0ZXN0
IHdhcyB3cm9uZyBmb3IgeWVhcnMgKGFsd2F5cwotCQk7IG5lZ2F0aXZlKSBzbyBpbnN0ZWFkIG9m
IGZpeGluZyB0aGUgdGVzdCBkbyB3aGF0IHdlCi0JCTsgdGVzdGVkIGFuZCBkb24ndCBib3RoZXIg
cHJvYmluZy4KLQkJbW92IGJ4LCBmYWtlX2ludDE1X3N0dWIKLQotLnByb3Rtb2RlOgotCQlUUkFD
RVIgJ3AnCi0uYW55bW9kZToKLQotLmNvcHlfbG9vcDoKLQkJcHVzaCBlc2kKLQkJcHVzaCBlZGkK
LQkJcHVzaCBlY3gKLQkJY21wIGVjeCw0MDAwaAotCQlqbmEgLnNhZmVfc2l6ZQotCQltb3YgZWN4
LDQwMDBoCi0uc2FmZV9zaXplOgotCQlwdXNoIGVjeAk7IFRyYW5zZmVyIHNpemUgdGhpcyBjeWNs
ZQotCQltb3YgZWF4LCBlc2kKLQkJbW92IFtNb3Zlcl9zcmMxXSwgc2kKLQkJc2hyIGVheCwgMTYK
LQkJbW92IFtNb3Zlcl9zcmMxKzJdLCBhbAotCQltb3YgW01vdmVyX3NyYzJdLCBhaAotCQltb3Yg
ZWF4LCBlZGkKLQkJbW92IFtNb3Zlcl9kc3QxXSwgZGkKLQkJc2hyIGVheCwgMTYKLQkJbW92IFtN
b3Zlcl9kc3QxKzJdLCBhbAotCQltb3YgW01vdmVyX2RzdDJdLCBhaAotCQltb3Ygc2ksTW92ZXIK
LQkJbW92IGFoLCA4N2gKLQkJc2hsIGN4LDEJOyBDb252ZXJ0IHRvIDE2LWJpdCB3b3JkcwotCQlj
YWxsIGJ4CQk7IElOVCAxNWggc3R1YgotCQlwb3AgZWF4CQk7IFRyYW5zZmVyIHNpemUgdGhpcyBj
eWNsZQotCQlwb3AgZWN4Ci0JCXBvcCBlZGkKLQkJcG9wIGVzaQotCQlqYyAuZXJyb3IKLQkJbGVh
IGVzaSxbZXNpKzQqZWF4XQotCQlsZWEgZWRpLFtlZGkrNCplYXhdCi0JCXN1YiBlY3gsIGVheAot
CQlqbnogLmNvcHlfbG9vcAotCQk7IENGID0gMAotLmVycm9yOgotLmRvbmU6Ci0JCXBvcCBlYnAK
LQkJcG9wIGVkeAotCQlwb3AgZWJ4Ci0JCXBvcCBlYXgKLQkJcmV0Ci0KLXJlYWxfaW50MTVfc3R1
YjoKLQkJaW50IDE1aAotCQljbGkJCTsgU29tZSBCSU9TZXMgZW5hYmxlIGludGVycnVwdHMgb24g
SU5UIDE1aAotCQlyZXQKLQotZmFrZV9pbnQxNV9zdHViOgotCQlwdXNoZgotCQljYWxsIGZhciBb
T2xkSW50MTVdCi0JCWNsaQotCQlyZXQKLQotJWlmZGVmIERFQlVHX1RSQUNFUlMKLWRlYnVnX3Ry
YWNlcjoJcHVzaGFkCi0JCXB1c2hmZAotCQltb3YgYnAsc3AKLQkJbW92IGJ4LFticCs5KjRdCi0J
CW1vdiBhbCxbY3M6YnhdCi0JCWluYyB3b3JkIFticCs5KjRdCi0JCW1vdiBhaCwwRWgKLQkJbW92
IGJ4LDcKLQkJaW50IDEwaAotCQlwb3BmZAotCQlwb3BhZAotCQlyZXQKLSVlbmRpZgotCi0JCXNl
Y3Rpb24gLmRhdGEKLQkJYWxpZ25iIDIKLUludDEzRnVuY3MJZHcgUmVzZXQJCTsgMDBoIC0gUkVT
RVQKLQkJZHcgR2V0U3RhdHVzCQk7IDAxaCAtIEdFVCBTVEFUVVMKLQkJZHcgUmVhZAkJCTsgMDJo
IC0gUkVBRAotCQlkdyBXcml0ZQkJOyAwM2ggLSBXUklURQotCQlkdyBWZXJpZnkJCTsgMDRoIC0g
VkVSSUZZCi0JCWR3IEludmFsaWQJCTsgMDVoIC0gRk9STUFUIFRSQUNLCi0JCWR3IEludmFsaWQJ
CTsgMDZoIC0gRk9STUFUIFRSQUNLIEFORCBTRVQgQkFEIEZMQUdTCi0JCWR3IEludmFsaWQJCTsg
MDdoIC0gRk9STUFUIERSSVZFIEFUIFRSQUNLCi0JCWR3IEdldFBhcm1zCQk7IDA4aCAtIEdFVCBQ
QVJBTUVURVJTCi0JCWR3IEluaXRXaXRoUGFybXMJOyAwOWggLSBJTklUSUFMSVpFIENPTlRST0xM
RVIgV0lUSCBEUklWRSBQQVJBTUVURVJTCi0JCWR3IEludmFsaWQJCTsgMEFoCi0JCWR3IEludmFs
aWQJCTsgMEJoCi0JCWR3IFNlZWsJCQk7IDBDaCAtIFNFRUsgVE8gQ1lMSU5ERVIKLQkJZHcgUmVz
ZXQJCTsgMERoIC0gUkVTRVQgSEFSRCBESVNLUwotCQlkdyBJbnZhbGlkCQk7IDBFaAotCQlkdyBJ
bnZhbGlkCQk7IDBGaAotCQlkdyBDaGVja0lmUmVhZHkJCTsgMTBoIC0gQ0hFQ0sgSUYgUkVBRFkK
LQkJZHcgUmVjYWxpYnJhdGUJCTsgMTFoIC0gUkVDQUxJQlJBVEUKLQkJZHcgSW52YWxpZAkJOyAx
MmgKLQkJZHcgSW52YWxpZAkJOyAxM2gKLQkJZHcgSW52YWxpZAkJOyAxNGgKLQkJZHcgR2V0RHJp
dmVUeXBlCQk7IDE1aCAtIEdFVCBEUklWRSBUWVBFCi0JCWR3IERldGVjdENoYW5nZQkJOyAxNmgg
LSBERVRFQ1QgRFJJVkUgQ0hBTkdFCi0laWYgRURECi0JCWR3IEludmFsaWQJCTsgMTdoCi0JCWR3
IEludmFsaWQJCTsgMThoCi0JCWR3IEludmFsaWQJCTsgMTloCi0JCWR3IEludmFsaWQJCTsgMUFo
Ci0JCWR3IEludmFsaWQJCTsgMUJoCi0JCWR3IEludmFsaWQJCTsgMUNoCi0JCWR3IEludmFsaWQJ
CTsgMURoCi0JCWR3IEludmFsaWQJCTsgMUVoCi0JCWR3IEludmFsaWQJCTsgMUZoCi0JCWR3IElu
dmFsaWQJCTsgMjBoCi0JCWR3IFJlYWRNdWx0CQk7IDIxaCAtIFJFQUQgTVVMVElQTEUKLQkJZHcg
V3JpdGVNdWx0CQk7IDIyaCAtIFdSSVRFIE1VTFRJUExFCi0JCWR3IFNldE1vZGUJCTsgMjNoIC0g
U0VUIENPTlRST0xMRVIgRkVBVFVSRVMKLQkJZHcgU2V0TW9kZQkJOyAyNGggLSBTRVQgTVVMVElQ
TEUgTU9ERQotCQlkdyBJbnZhbGlkCQk7IDI1aCAtIElERU5USUZZIERSSVZFCi0JCWR3IEludmFs
aWQJCTsgMjZoCi0JCWR3IEludmFsaWQJCTsgMjdoCi0JCWR3IEludmFsaWQJCTsgMjhoCi0JCWR3
IEludmFsaWQJCTsgMjloCi0JCWR3IEludmFsaWQJCTsgMkFoCi0JCWR3IEludmFsaWQJCTsgMkJo
Ci0JCWR3IEludmFsaWQJCTsgMkNoCi0JCWR3IEludmFsaWQJCTsgMkRoCi0JCWR3IEludmFsaWQJ
CTsgMkVoCi0JCWR3IEludmFsaWQJCTsgMkZoCi0JCWR3IEludmFsaWQJCTsgMzBoCi0JCWR3IElu
dmFsaWQJCTsgMzFoCi0JCWR3IEludmFsaWQJCTsgMzJoCi0JCWR3IEludmFsaWQJCTsgMzNoCi0J
CWR3IEludmFsaWQJCTsgMzRoCi0JCWR3IEludmFsaWQJCTsgMzVoCi0JCWR3IEludmFsaWQJCTsg
MzZoCi0JCWR3IEludmFsaWQJCTsgMzdoCi0JCWR3IEludmFsaWQJCTsgMzhoCi0JCWR3IEludmFs
aWQJCTsgMzloCi0JCWR3IEludmFsaWQJCTsgM0FoCi0JCWR3IEludmFsaWQJCTsgM0JoCi0JCWR3
IEludmFsaWQJCTsgM0NoCi0JCWR3IEludmFsaWQJCTsgM0RoCi0JCWR3IEludmFsaWQJCTsgM0Vo
Ci0JCWR3IEludmFsaWQJCTsgM0ZoCi0JCWR3IEludmFsaWQJCTsgNDBoCi0JCWR3IEVERFByZXNl
bmNlCQk7IDQxaCAtIEVERCBQUkVTRU5DRSBERVRFQ1QKLQkJZHcgRUREUmVhZAkJOyA0MmggLSBF
REQgUkVBRAotCQlkdyBFRERXcml0ZQkJOyA0M2ggLSBFREQgV1JJVEUKLQkJZHcgRUREVmVyaWZ5
CQk7IDQ0aCAtIEVERCBWRVJJRlkKLQkJZHcgRURETG9jawkJOyA0NWggLSBFREQgTE9DSy9VTkxP
Q0sgTUVESUEKLQkJZHcgRURERWplY3QJCTsgNDZoIC0gRUREIEVKRUNUCi0JCWR3IEVERFNlZWsJ
CTsgNDdoIC0gRUREIFNFRUsKLQkJZHcgRURER2V0UGFybXMJCTsgNDhoIC0gRUREIEdFVCBQQVJB
TUVURVJTCi0JCWR3IEVERERldGVjdENoYW5nZQk7IDQ5aCAtIEVERCBNRURJQSBDSEFOR0UgU1RB
VFVTCi0lZW5kaWYKLQotSW50MTNGdW5jc0VuZAllcXUgJAotSW50MTNGdW5jc0NudAllcXUgKElu
dDEzRnVuY3NFbmQtSW50MTNGdW5jcykgPj4gMQotCi0KLQkJYWxpZ25iIDgsIGRiIDAKLVNoYWtl
cgkJZHcgU2hha2VyRW5kLSQKLQkJZGQgMAkJCTsgUG9pbnRlciB0byBzZWxmCi0JCWR3IDAKLQot
U2hha2VyX1JNRFM6CWRkIDB4MDAwMGZmZmYJCTsgNjRLIGRhdGEgc2VnbWVudAotCQlkZCAweDAw
MDA5MzAwCi0KLVNoYWtlcl9EUzoJZGQgMHgwMDAwZmZmZgkJOyA0R0IgZGF0YSBzZWdtZW50Ci0J
CWRkIDB4MDA4ZjkzMDAKLQotU2hha2VyRW5kCWVxdSAkCi0KLQkJYWxpZ25iIDgsIGRiIDAKLQot
TW92ZXIJCWRkIDAsIDAsIDAsIDAJCTsgTXVzdCBiZSB6ZXJvCi0JCWR3IDBmZmZmaAkJOyA2NCBL
IHNlZ21lbnQgc2l6ZQotTW92ZXJfc3JjMToJZGIgMCwgMCwgMAkJOyBMb3cgMjQgYml0cyBvZiBz
b3VyY2UgYWRkeQotCQlkYiA5M2gJCQk7IEFjY2VzcyByaWdodHMKLQkJZGIgMDBoCQkJOyBFeHRl
bmRlZCBhY2Nlc3MgcmlnaHRzCi1Nb3Zlcl9zcmMyOglkYiAwCQkJOyBIaWdoIDggYml0cyBvZiBz
b3VyY2UgYWRkeQotCQlkdyAwZmZmZmgJCTsgNjQgSyBzZWdtZW50IHNpemUKLU1vdmVyX2RzdDE6
CWRiIDAsIDAsIDAJCTsgTG93IDI0IGJpdHMgb2YgdGFyZ2V0IGFkZHkKLQkJZGIgOTNoCQkJOyBB
Y2Nlc3MgcmlnaHRzCi0JCWRiIDAwaAkJCTsgRXh0ZW5kZWQgYWNjZXNzIHJpZ2h0cwotTW92ZXJf
ZHN0MjoJZGIgMAkJCTsgSGlnaCA4IGJpdHMgb2Ygc291cmNlIGFkZHkKLU1vdmVyX2R1bW15MjoJ
ZGQgMCwgMCwgMCwgMAkJOyBNb3JlIHNwYWNlIGZvciB0aGUgQklPUwotCi0JCWFsaWduYiA0LCBk
YiAwCi1NZW1EaXNrX0luZm8JZXF1ICQJCQk7IFBvaW50ZWQgdG8gYnkgaW5zdGFsbGF0aW9uIGNo
ZWNrCi1NRElfQnl0ZXMJZHcgTURJX0xlbgkJOyBUb3RhbCBieXRlcyBpbiBNREkgc3RydWN0dXJl
Ci1NRElfVmVyc2lvbglkYiBWRVJTSU9OX01JTk9SLCBWRVJTSU9OX01BSk9SCTsgTUVNRElTSyB2
ZXJzaW9uCi0KLVBhdGNoQXJlYQllcXUgJAkJCTsgVGhpcyBnZXRzIGZpbGxlZCBpbiBieSB0aGUg
aW5zdGFsbGVyCi0KLURpc2tCdWYJCWRkIDAJCQk7IExpbmVhciBhZGRyZXNzIG9mIGhpZ2ggbWVt
b3J5IGRpc2sKLURpc2tTaXplCWRkIDAJCQk7IFNpemUgb2YgZGlzayBpbiBibG9ja3MKLUNvbW1h
bmRMaW5lCWR3IDAsIDAJCQk7IEZhciBwb2ludGVyIHRvIHNhdmVkIGNvbW1hbmQgbGluZQotCi1P
bGRJbnQxMwlkZCAwCQkJOyBJTlQgMTNoIGluIGNoYWluCi1PbGRJbnQxNQlkZCAwCQkJOyBJTlQg
MTVoIGluIGNoYWluCi0KLU9sZERvc01lbQlkdyAwCQkJOyBPbGQgcG9zaXRpb24gb2YgRE9TIG1l
bSBlbmQKLUJvb3RMb2FkZXJJRAlkYiAwCQkJOyBCb290IGxvYWRlciBJRCBmcm9tIGhlYWRlcgot
CQlkYiAwCQkJOyBwYWQKLQotRFBUX3B0cgkJZHcgMAkJCTsgSWYgbm9uemVybywgcG9pbnRlciB0
byBEUFQKLQkJCQkJOyBPcmlnaW5hbCBEUFQgcG9pbnRlciBmb2xsb3dzCi0KLU1ESV9MZW4JCWVx
dSAkLU1lbURpc2tfSW5mbwotCi07IC0tLS0gTURJIHN0cnVjdHVyZSBlbmRzIGhlcmUgLS0tCi1J
bnQxM01heEZ1bmMJZGIgSW50MTNGdW5jc0NudC0xCTsgTWF4IElOVCAxM2ggZnVuY3Rpb24gKHRv
IGRpc2FibGUgRUREKQotCQlkYiAwCQkJOyBwYWQKLQotCQlkdyAwCQkJOyBwYWQKLU1lbUludDE1
ODgJZHcgMAkJCTsgMU1CLTY1TUIgbWVtb3J5IGFtb3VudCAoMUspCi0KLUN5bGluZGVycwlkdyAw
CQkJOyBDeWxpbmRlciBjb3VudAotSGVhZHMJCWR3IDAJCQk7IEhlYWQgY291bnQKLVNlY3RvcnMJ
CWRkIDAJCQk7IFNlY3RvciBjb3VudCAoemVyby1leHRlbmRlZCkKLQotTWVtMU1CCQlkZCAwCQkJ
OyAxTUItMTZNQiBtZW1vcnkgYW1vdW50ICgxSykKLU1lbTE2TUIJCWRkIDAJCQk7IDE2TUItNEcg
bWVtb3J5IGFtb3VudCAoNjRLKQotCi1Ecml2ZU5vCQlkYiAwCQkJOyBPdXIgZHJpdmUgbnVtYmVy
Ci1Ecml2ZVR5cGUJZGIgMAkJCTsgT3VyIGRyaXZlIHR5cGUgKGZsb3BwaWVzKQotRHJpdmVDbnQJ
ZGIgMAkJCTsgRHJpdmUgY291bnQgKGZyb20gdGhlIEJJT1MpCi0KLUNvbmZpZ0ZsYWdzCWRiIDAJ
CQk7IEJpdCAwIC0gcmVhZG9ubHkKLQotTXlTdGFjawkJZHcgMAkJCTsgT2Zmc2V0IG9mIHN0YWNr
Ci1TdGF0dXNQdHIJZHcgMAkJCTsgV2hlcmUgdG8gc2F2ZSBzdGF0dXMgKHplcm9zZWcgcHRyKQot
Ci1EUFQJCXRpbWVzIDE2IGRiIDAJCTsgQklPUyBwYXJhbWV0ZXIgdGFibGUgcG9pbnRlciAoZmxv
cHBpZXMpCi1PbGRJbnQxRQlkZCAwCQkJOyBQcmV2aW91cyBJTlQgMUUgcG9pbnRlciAoRFBUKQot
Ci0laWYgRURECi1FRERfRFBUOgotLmxlbmd0aAkJZHcgMzAKLS5pbmZvCQlkdyAwMDI5aAotCQk7
IEJpdCAwIC0gRE1BIGJvdW5kYXJpZXMgaGFuZGxlZCB0cmFuc3BhcmVudGx5Ci0JCTsgQml0IDMg
LSBEZXZpY2Ugc3VwcG9ydHMgd3JpdGUgdmVyaWZ5Ci0JCTsgQml0IDUgLSBNZWRpYSBpcyBsb2Nr
YWJsZQotLmN5bGluZGVycwlkZCAwCQkJOyBGaWxsZWQgaW4gYnkgaW5zdGFsbGVyCi0uaGVhZHMJ
CWRkIDAJCQk7IEZpbGxlZCBpbiBieSBpbnN0YWxsZXIKLS5zZWN0b3JzCWRkIDAJCQk7IEZpbGxl
ZCBpbiBieSBpbnN0YWxsZXIKLS50b3RhbHNpemUJZGQgMCwgMAkJCTsgRmlsbGVkIGluIGJ5IGlu
c3RhbGxlcgotLmJ5dGVzcGVyc2VjCWR3IFNFQ1RPUlNJWkUKLS5lZGR0YWJsZQlkdyAtMSwgLTEJ
CTsgSW52YWxpZCBEUFRFIHBvaW50ZXIKLQotJWVuZGlmCi0KLQkJOyBFbmQgcGF0Y2ggYXJlYQot
U3RhY2sJCWRkIDAJCQk7IFNhdmVkIFNTOkVTUCBvbiBpbnZvY2F0aW9uCi0JCWR3IDAKLVNhdmVk
QVgJCWR3IDAJCQk7IEFYIHNhdmVkIG9uIGludm9jYXRpb24KLQotCQlhbGlnbmIgNCwgZGIgMAkJ
OyBXZSAqTVVTVCogZW5kIG9uIGEgZHdvcmQgYm91bmRhcnkKLQotRTgyMFRhYmxlCWVxdSAkCQkJ
OyBUaGUgaW5zdGFsbGVyIGxvYWRzIHRoZSBFODIwIHRhYmxlIGhlcmUKLVRvdGFsU2l6ZQllcXUg
JAkJCTsgRW5kIHBvaW50ZXIKKyVpbmNsdWRlICJtZW1kaXNrLmluYyIKZGlmZiAtLWdpdCBhL21l
bWRpc2svbWVtZGlzay5pbmMgYi9tZW1kaXNrL21lbWRpc2suaW5jCm5ldyBmaWxlIG1vZGUgMTAw
NjQ0CmluZGV4IDAwMDAwMDAuLjJiNWI0ZTAKLS0tIC9kZXYvbnVsbAorKysgYi9tZW1kaXNrL21l
bWRpc2suaW5jCkBAIC0wLDAgKzEsOTg3IEBACis7IC0qLSBmdW5kYW1lbnRhbCAtKi0gKGFzbS1t
b2RlIHN1Y2tzKQorOyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCis7Cis7ICBtZW1kaXNrLmluYworOwor
OyAgQSBwcm9ncmFtIHRvIGVtdWxhdGUgYW4gSU5UIDEzaCBkaXNrIEJJT1MgZnJvbSBhICJkaXNr
IiBpbiBleHRlbmRlZAorOyAgbWVtb3J5LgorOworOyAgIENvcHlyaWdodCAyMDAxLTIwMDggSC4g
UGV0ZXIgQW52aW4gLSBBbGwgUmlnaHRzIFJlc2VydmVkCis7Cis7ICBUaGlzIHByb2dyYW0gaXMg
ZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQorOyAg
aXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBw
dWJsaXNoZWQgYnkKKzsgIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIEluYy4sIDUzIFRl
bXBsZSBQbGFjZSBTdGUgMzMwLAorOyAgQm9zdG9uIE1BIDAyMTExLTEzMDcsIFVTQTsgZWl0aGVy
IHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKKzsgIChhdCB5b3VyIG9wdGlvbikgYW55IGxh
dGVyIHZlcnNpb247IGluY29ycG9yYXRlZCBoZXJlaW4gYnkgcmVmZXJlbmNlLgorOworOyAqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqCisKKyVpZm5kZWYgREVQRU5ECislaW5jbHVkZQkiLi4vdmVyc2lvbi5n
ZW4iCislZW5kaWYKKworOyAlZGVmaW5lIERFQlVHX1RSQUNFUlMJCQk7IFVuY29tbWVudCB0byBn
ZXQgZGVidWdnaW5nIHRyYWNlcnMKKworJWlmZGVmIFdJVEhfRURECislZGVmaW5lIEVERCAxCisl
ZWxzZQorJWRlZmluZSBFREQgMAorJWVuZGlmCisKKyVpZmRlZiBERUJVR19UUkFDRVJTCisKKyVt
YWNybyBUUkFDRVIJMQorCWNhbGwgZGVidWdfdHJhY2VyCisJZGIgJTEKKyVlbmRtYWNybworCisl
ZWxzZQk7IERFQlVHX1RSQUNFUlMKKworJW1hY3JvCVRSQUNFUgkxCislZW5kbWFjcm8KKworJWVu
ZGlmCTsgREVCVUdfVFJBQ0VSUworCislZGVmaW5lIENPTkZJR19SRUFET05MWQkweDAxCislZGVm
aW5lIENPTkZJR19SQVcJMHgwMgorJWRlZmluZSBDT05GSUdfU0FGRUlOVAkweDA0CislZGVmaW5l
IENPTkZJR19CSUdSQVcJMHgwOAkJOyBNVVNUIGJlIDghCisKKwkJb3JnIDBoCisKKyVkZWZpbmUg
U0VDVE9SU0laRV9MRzIJOQkJOyBsb2cyKHNlY3RvciBzaXplKQorJWRlZmluZQlTRUNUT1JTSVpF
CSgxIDw8IFNFQ1RPUlNJWkVfTEcyKQorCisJCTsgUGFyYW1ldGVyIHJlZ2lzdGVycyBkZWZpbml0
aW9uOyB0aGlzIGlzIHRoZSBkZWZpbml0aW9uCisJCTsgb2YgdGhlIHN0YWNrIGZyYW1lLgorJWRl
ZmluZQkJUF9EUwkJd29yZCBbYnArMzRdCislZGVmaW5lCQlQX0VTCQl3b3JkIFticCszMl0KKyVk
ZWZpbmUJCVBfRUFYCQlkd29yZCBbYnArMjhdCislZGVmaW5lCQlQX0hBWAkJd29yZCBbYnArMzBd
CislZGVmaW5lCQlQX0FYCQl3b3JkIFticCsyOF0KKyVkZWZpbmUJCVBfQUwJCWJ5dGUgW2JwKzI4
XQorJWRlZmluZQkJUF9BSAkJYnl0ZSBbYnArMjldCislZGVmaW5lCQlQX0VDWAkJZHdvcmQgW2Jw
KzI0XQorJWRlZmluZQkJUF9IQ1gJCXdvcmQgW2JwKzI2XQorJWRlZmluZQkJUF9DWAkJd29yZCBb
YnArMjRdCislZGVmaW5lCQlQX0NMCQlieXRlIFticCsyNF0KKyVkZWZpbmUJCVBfQ0gJCWJ5dGUg
W2JwKzI1XQorJWRlZmluZQkJUF9FRFgJCWR3b3JkIFticCsyMF0KKyVkZWZpbmUJCVBfSERYCQl3
b3JkIFticCsyMl0KKyVkZWZpbmUJCVBfRFgJCXdvcmQgW2JwKzIwXQorJWRlZmluZQkJUF9ETAkJ
Ynl0ZSBbYnArMjBdCislZGVmaW5lCQlQX0RICQlieXRlIFticCsyMV0KKyVkZWZpbmUJCVBfRUJY
CQlkd29yZCBbYnArMTZdCislZGVmaW5lCQlQX0hCWAkJd29yZCBbYnArMThdCislZGVmaW5lCQlQ
X0hCWEwJCWJ5dGUgW2JwKzE4XQorJWRlZmluZQkJUF9CWAkJd29yZCBbYnArMTZdCislZGVmaW5l
CQlQX0JMCQlieXRlIFticCsxNl0KKyVkZWZpbmUJCVBfQkgJCWJ5dGUgW2JwKzE3XQorJWRlZmlu
ZQkJUF9FQlAJCWR3b3JkIFticCs4XQorJWRlZmluZQkJUF9CUAkJd29yZCBbYnArOF0KKyVkZWZp
bmUJCVBfRVNJCQlkd29yZCBbYnArNF0KKyVkZWZpbmUJCVBfU0kJCXdvcmQgW2JwKzRdCislZGVm
aW5lCQlQX0VESQkJZHdvcmQgW2JwXQorJWRlZmluZQkJUF9ESQkJd29yZCBbYnBdCisKKwkJc2Vj
dGlvbiAudGV4dAorCQk7IFRoZXNlIHBvaW50ZXJzIGFyZSB1c2VkIGJ5IHRoZSBpbnN0YWxsZXIg
YW5kCisJCTsgbXVzdCBiZSBmaXJzdCBpbiB0aGUgYmluYXJ5CitQb2ludGVyczoJZHcgSW50MTNT
dGFydAorCQlkdyBJbnQxNVN0YXJ0CisJCWR3IFBhdGNoQXJlYQorCQlkdyBUb3RhbFNpemUKKwkJ
ZHcgSXJldFB0cgorCitJcmV0UHRyCQllcXUgSW50MTNTdGFydC5pcmV0CitJbnQxM1N0YXJ0Ogor
CQk7IFN3YXAgc3RhY2sKKwkJbW92IFtjczpTdGFja10sZXNwCisJCW1vdiBbY3M6U2F2ZWRBWF0s
YXgKKwkJbW92IGF4LHNzCisJCW1vdiBbY3M6U3RhY2srNF0sYXgKKwkJbW92IGF4LGNzCisJCW1v
diBzcyxheAorCQltb3Ygc3AsW2NzOk15U3RhY2tdCisKKwkJOyBTZWUgaWYgREwgcG9pbnRzIHRv
IG91ciBjbGFzcyBvZiBkZXZpY2UgKEZELCBIRCkKKwkJcHVzaCBkeAorCQlwdXNoIGR4CisJCXhv
ciBkbCxbY3M6RHJpdmVOb10KKwkJcG9wIGR4CisJCWpzIC5ub21hdGNoCQk7IElmIFNGPTAsIHdl
IGhhdmUgYSBjbGFzcyBtYXRjaCBoZXJlCisJCWp6IC5vdXJfZHJpdmUJCTsgSWYgWkY9MSwgd2Ug
aGF2ZSBhbiBleGFjdCBtYXRjaAorCQljbXAgZGwsW2NzOkRyaXZlTm9dCisJCWpiIC5ub21hdGNo
CQk7IERyaXZlIDwgT3VyIGRyaXZlCisJCWRlYyBkbAkJCTsgRHJpdmUgPiBPdXIgZHJpdmUsIGFk
anVzdCBkcml2ZSAjCisubm9tYXRjaDoKKwkJbW92IGF4LFtjczpTYXZlZEFYXQorCQlwdXNoZgor
CQljYWxsIGZhciBbY3M6T2xkSW50MTNdCisJCXB1c2hmCisJCXB1c2ggYnAKKwkJbW92IGJwLHNw
CisJCWNtcCBieXRlIFtjczpTYXZlZEFYKzFdLDA4aAorCQlqZSAubm9yZXN0b3JlZGwKKwkJY21w
IGJ5dGUgW2NzOlNhdmVkQVgrMV0sMTVoCisJCWpuZSAucmVzdG9yZWRsCisJCXRlc3QgYnl0ZSBb
YnArNF0sODBoCTsgSGFyZCBkaXNrPworCQlqbnogLm5vcmVzdG9yZWRsCisucmVzdG9yZWRsOgor
CQltb3YgZGwsW2JwKzRdCisubm9yZXN0b3JlZGw6CisJCXB1c2ggYXgKKwkJcHVzaCBlYngKKwkJ
cHVzaCBkcworCQltb3YgYXgsW2JwKzJdCQk7IEZsYWdzCisJCWxkcyBlYngsW2NzOlN0YWNrXQor
CQltb3YgW2J4KzRdLGFsCQk7IEFyaXRobWV0cmljIGZsYWdzCisJCXBvcCBkcworCQlwb3AgZWJ4
CisJCXBvcCBheAorCQlwb3AgYnAKKwkJbHNzIGVzcCxbY3M6U3RhY2tdCisuaXJldDoJCWlyZXQK
KworLm91cl9kcml2ZToKKwkJOyBTZXQgdXAgc3RhbmRhcmQgZW50cnkgZnJhbWUKKwkJcHVzaCBk
cworCQlwdXNoIGVzCisJCW1vdiBkcyxheAorCQltb3YgZXMsYXgKKwkJbW92IGF4LFtTYXZlZEFY
XQorCQlwdXNoYWQKKwkJbW92IGJwLHNwCQk7IFBvaW50IEJQIHRvIHRoZSBlbnRyeSBzdGFjayBm
cmFtZQorCQlUUkFDRVIgJ0YnCisJCTsgTm90ZTogQUggPT0gUF9BSCBoZXJlCisJCWNtcCBhaCxb
SW50MTNNYXhGdW5jXQorCQlqYSBJbnZhbGlkX2p1bXAKKwkJeG9yIGFsLGFsCQk7IEFMID0gMCBp
cyBzdGFuZGFyZCBlbnRyeSBjb25kaXRpb24KKwkJbW92IGRpLGF4CisJCXNociBkaSw3CQk7IENv
bnZlcnQgQUggdG8gYW4gb2Zmc2V0IGluIERJCisJCWNhbGwgW0ludDEzRnVuY3MrZGldCisKK0Rv
bmU6CQk7IFN0YW5kYXJkIHJvdXRpbmUgZm9yIHJldHVybgorCQltb3YgUF9BWCxheAorRG9uZVdl
aXJkOgorCQlUUkFDRVIgJ0QnCisJCXhvciBieCxieAorCQltb3YgZXMsYngKKwkJbW92IGJ4LFtT
dGF0dXNQdHJdCisJCW1vdiBbZXM6YnhdLGFoCQk7IFNhdmUgc3RhdHVzCisJCWFuZCBhaCxhaAor
CisJCWxkcyBlYngsW1N0YWNrXQorCQk7IFRoaXMgc2V0cyB0aGUgbG93IGJ5dGUgKHRoZSBhcml0
aG1ldHJpYyBmbGFncykgb2YgdGhlCisJCTsgRkxBR1Mgb24gc3RhY2sgdG8gZWl0aGVyIDAwaCAo
bm8gZmxhZ3MpIG9yIDAxaCAoQ0YpCisJCTsgZGVwZW5kaW5nIG9uIGlmIEFIIHdhcyB6ZXJvIG9y
IG5vdC4KKwkJc2V0bnogW2J4KzRdCQk7IFNldCBDRiBpZmYgZXJyb3IKKwkJcG9wYWQKKwkJcG9w
IGVzCisJCXBvcCBkcworCQlsc3MgZXNwLFtjczpTdGFja10KKwkJaXJldAorCitSZXNldDoKKwkJ
OyBSZXNldCBhZmZlY3RzIG11bHRpcGxlIGRyaXZlcywgc28gd2UgbmVlZCB0byBwYXNzIGl0IG9u
CisJCVRSQUNFUiAnUicKKwkJeG9yIGF4LGF4CQk7IEJvdHRvbSBvZiBtZW1vcnkKKwkJbW92IGVz
LGF4CisJCXRlc3QgZGwsZGwJCTsgQWx3YXlzIHBhc3MgaXQgb24gaWYgd2UgYXJlIHJlc2V0dGlu
ZyBIRAorCQlqcyAuaGFyZF9kaXNrCQk7IEJpdCA3IHNldAorCQk7IFNvbWUgQklPU2VzIGdldCB2
ZXJ5IHVuaGFwcHkgaWYgd2UgcGFzcyBhIHJlc2V0IGZsb3BweQorCQk7IGNvbW1hbmQgdG8gdGhl
bSBhbmQgZG9uJ3QgYWN0dWFsbHkgaGF2ZSBhbnkgZmxvcHBpZXMuCisJCTsgVGhpcyBpcyBhIGJ1
ZywgYnV0IHdlIGhhdmUgdG8gZGVhbCB3aXRoIGl0IG5vbnRoZWxlc3MuCisJCTsgVGhlcmVmb3Jl
LCBpZiB3ZSBhcmUgdGhlICpPTkxZKiBmbG9wcHkgZHJpdmUsIGFuZCB0aGUKKwkJOyB1c2VyIGRp
ZG4ndCByZXF1ZXN0IEhEIHJlc2V0LCB0aGVuIGp1c3QgZHJvcCB0aGUgY29tbWFuZC4KKwkJOyBC
SU9TIGVxdWlwbWVudCBieXRlLCB0b3AgdHdvIGJpdHMgKyAxID09IHRvdGFsICMgb2YgZmxvcHBp
ZXMKKwkJdGVzdCBieXRlIFtlczoweDQxMF0sMEMwaAorCQlqeiBzdWNjZXNzCisJCWptcCAucGFz
c19vbgkJOyAuLi4gb3RoZXJ3aXNlIHBhc3MgaXQgdG8gdGhlIEJJT1MKKy5oYXJkX2Rpc2s6CisJ
CTsgLi4uIHNhbWUgdGhpbmcgZm9yIGhhcmQgZGlza3MsIHNpZ2ggLi4uCisJCWNtcCBieXRlIFtl
czoweDQ3NV0sMQk7IEJJT1MgdmFyaWFibGUgZm9yIG51bWJlciBvZiBoYXJkIGRpc2tzCisJCWpi
ZSBzdWNjZXNzCisKKy5wYXNzX29uOgorCQlwb3AgYXgJCQk7IERyb3AgcmV0dXJuIGFkZHJlc3MK
KwkJcG9wYWQJCQk7IFJlc3RvcmUgYWxsIHJlZ2lzdGVycworCQlwb3AgZXMKKwkJcG9wIGRzCisJ
CWxzcyBlc3AsW2NzOlN0YWNrXQk7IFJlc3RvcmUgdGhlIHN0YWNrCisJCWFuZCBkbCw4MGgJCTsg
Q2xlYXIgYWxsIGJ1dCB0aGUgdHlwZSBiaXQKKwkJam1wIGZhciBbY3M6T2xkSW50MTNdCisKKwor
SW52YWxpZDoKKwkJcG9wIGR4CQkJOyBEcm9wIHJldHVybiBhZGRyZXNzCitJbnZhbGlkX2p1bXA6
CisJCVRSQUNFUiAnSScKKwkJbW92IGFoLDAxaAkJOyBVbnN1cHBvcnRlZCBmdW5jdGlvbgorCQlq
bXAgc2hvcnQgRG9uZQorCitHZXREcml2ZVR5cGU6CisJCXRlc3QgYnl0ZSBbRHJpdmVOb10sODBo
CisJCW1vdiBibCwwMmgJCTsgVHlwZSAwMmggPSBmbG9wcHkgd2l0aCBjaGFuZ2VsaW5lCisJCWp6
IC5mbG9wcHkKKwkJOyBIYXJkIGRpc2tzIG9ubHkuLi4KKwkJaW5jIGJ4CQkJOyBUeXBlID0gMDNo
CisJCW1vdiBkeCxbRGlza1NpemVdCTsgUmV0dXJuIHRoZSBkaXNrIHNpemUgaW4gc2VjdG9ycwor
CQltb3YgUF9EWCxkeAorCQltb3YgY3gsW0Rpc2tTaXplKzJdCisJCW1vdiBQX0NYLGN4CisuZmxv
cHB5OgorCQltb3YgUF9BSCxibAkJOyAwMmggZmxvcHB5LCAwM2ggaGFyZCBkaXNrCisJCXBvcCBh
eAkJCTsgRHJvcCByZXR1cm4gYWRkcmVzcworCQl4b3IgYXgsYXgJCTsgU3VjY2Vzcy4uLgorCQlq
bXAgRG9uZVdlaXJkCQk7IEJ1dCBkb24ndCBzdGljayBpdCBpbnRvIFBfQVgKKworR2V0U3RhdHVz
OgorCQl4b3IgYXgsYXgKKwkJbW92IGVzLGF4CisJCW1vdiBieCxbU3RhdHVzUHRyXQorCQltb3Yg
YWgsW2J4XQkJOyBDb3B5IGxhc3Qgc3RhdHVzCisJCXJldAorCitSZWFkTXVsdDoKKwkJVFJBQ0VS
ICdtJworUmVhZDoKKwkJVFJBQ0VSICdSJworCQljYWxsIHNldHVwX3JlZ3MKK2RvX2NvcHk6CisJ
CVRSQUNFUiAnPCcKKwkJY2FsbCBiY29weQorCQlUUkFDRVIgJz4nCisJCW1vdnp4IGF4LFBfQUwJ
CTsgQUggPSAwLCBBTCA9IHRyYW5zZmVyIGNvdW50CisJCXJldAorCitXcml0ZU11bHQ6CisJCVRS
QUNFUiAnTScKK1dyaXRlOgorCQlUUkFDRVIgJ1cnCisJCXRlc3QgYnl0ZSBbQ29uZmlnRmxhZ3Nd
LENPTkZJR19SRUFET05MWQorCQlqbnogLnJlYWRvbmx5CisJCWNhbGwgc2V0dXBfcmVncworCQl4
Y2hnIGVzaSxlZGkJCTsgT3Bwb3NpdGUgZGlyZWN0aW9uIG9mIGEgUmVhZCEKKwkJam1wIHNob3J0
IGRvX2NvcHkKKy5yZWFkb25seToJbW92IGFoLDAzaAkJOyBXcml0ZSBwcm90ZWN0ZWQgbWVkaXVt
CisJCXJldAorCisJCTsgVmVyaWZ5IGludGVncml0eTsganVzdCBib3VuZHMtY2hlY2sKK1NlZWs6
CitWZXJpZnk6CisJCWNhbGwgc2V0dXBfcmVncwkJOyBSZXR1cm5zIGVycm9yIGlmIGFwcHJvcHJp
YXRlCisJCTsgQW5kIGZhbGwgdGhyb3VnaCB0byBzdWNjZXNzCisKK0NoZWNrSWZSZWFkeToJCQkJ
OyBUaGVzZSBhcmUgYWx3YXlzLXN1Y2Nlc3NmdWwgbm9vcCBmdW5jdGlvbnMKK1JlY2FsaWJyYXRl
OgorSW5pdFdpdGhQYXJtczoKK0RldGVjdENoYW5nZToKK0VERERldGVjdENoYW5nZToKK0VERExv
Y2s6CitTZXRNb2RlOgorc3VjY2VzczoKKwkJeG9yIGF4LGF4CQk7IEFsd2F5cyBzdWNjZXNzZnVs
CisJCXJldAorCitHZXRQYXJtczoKKwkJVFJBQ0VSICdHJworCQltb3YgZGwsW0RyaXZlQ250XQk7
IENhY2hlZCBkYXRhCisJCW1vdiBQX0RMLGRsCisJCXRlc3QgYnl0ZSBbRHJpdmVOb10sODBoCisJ
CWpueiAuaGQKKwkJbW92IFBfREksRFBUCisJCW1vdiBQX0VTLGNzCisJCW1vdiBibCxbRHJpdmVU
eXBlXQorCQltb3YgUF9CTCxibAorLmhkOgorCQltb3YgYXgsW0N5bGluZGVyc10KKwkJZGVjIGF4
CQkJOyBXZSByZXBvcnQgdGhlIGhpZ2hlc3QgIywgbm90IHRoZSBjb3VudAorCQl4Y2hnIGFsLGFo
CisJCXNobCBhbCw2CisJCW9yIGFsLFtTZWN0b3JzXQorCQltb3YgUF9DWCxheAorCQltb3YgYXgs
W0hlYWRzXQorCQlkZWMgYXgKKwkJbW92IFBfREgsYWwKKworCQk7CisJCTsgSXMgdGhpcyBNRU1E
SVNLIGluc3RhbGxhdGlvbiBjaGVjaz8KKwkJOworCQljbXAgUF9IQVgsJ01FJworCQlqbmUgLm5v
dGljCisJCWNtcCBQX0hDWCwnTUQnCisJCWpuZSAubm90aWMKKwkJY21wIFBfSERYLCdJUycKKwkJ
am5lIC5ub3RpYworCQljbXAgUF9IQlgsJ0s/JworCQlqbmUgLm5vdGljCisKKwkJOyBNRU1ESVNL
IGluc3RhbGxhdGlvbiBjaGVjay4uLgorCQltb3YgUF9IQVgsJyFNJworCQltb3YgUF9IQ1gsJ0VN
JworCQltb3YgUF9IRFgsJ0RJJworCQltb3YgUF9IQlgsJ1NLJworCQltb3YgUF9FUyxjcworCQlt
b3YgUF9ESSxNZW1EaXNrX0luZm8KKworLm5vdGljOgorCQl4b3IgYXgsYXgKKwkJcmV0Cis7Cis7
IEVERCBmdW5jdGlvbnMgLS0gb25seSBpZiBlbmFibGVkCis7CislaWYgRURECitFRERQcmVzZW5j
ZToKKwkJVFJBQ0VSICdFJworCQlUUkFDRVIgJ2MnCisKKwkJY21wIFBfQlgsNTVBQWgKKwkJam5l
IEludmFsaWQKKwkJbW92IFBfQlgsMEFBNTVoCQk7IEVERCBzaWduYXR1cmUKKwkJbW92IFBfQVgs
MDMwMDBoCQk7IEVERCAzLjAKKwkJbW92IFBfQ1gsMDAwM2gJCTsgQml0IDAgLSBGaXhlZCBkaXNr
IGFjY2VzcyBzdWJzZXQKKwkJCQkJOyBCaXQgMSAtIExvY2tpbmcgYW5kIGVqZWN0aW5nIHN1YnNl
dAorCQlwb3AgYXgJCQk7IERyb3AgcmV0dXJuIGFkZHJlc3MKKwkJeG9yIGF4LGF4CQk7IFN1Y2Nl
c3MKKwkJam1wIERvbmVXZWlyZAkJOyBTdWNjZXNzLCBidXQgQUggIT0gMCwgc2lnaC4uLgorCitF
RERSZWFkOgorCQlUUkFDRVIgJ0UnCisJCVRSQUNFUiAncicKKworCQljYWxsIGVkZF9zZXR1cF9y
ZWdzCisJCWNhbGwgYmNvcHkKKwkJeG9yIGF4LGF4CisJCXJldAorCitFRERXcml0ZToKKwkJVFJB
Q0VSICdFJworCQlUUkFDRVIgJ3cnCisKKwkJY2FsbCBlZGRfc2V0dXBfcmVncworCQl4Y2hnIGVz
aSxlZGkKKwkJY2FsbCBiY29weQorCQl4b3IgYXgsYXgKKwkJcmV0CisKK0VERFZlcmlmeToKK0VE
RFNlZWs6CisJCWNhbGwgZWRkX3NldHVwX3JlZ3MJOyBKdXN0IGJvdW5kcyBjaGVja2luZworCQl4
b3IgYXgsYXgKKwkJcmV0CisKK0VEREdldFBhcm1zOgorCQlUUkFDRVIgJ0UnCisJCVRSQUNFUiAn
cCcKKworCQltb3YgZXMsUF9EUworCQltb3YgZGksUF9TSQorCQltb3Ygc2ksRUREX0RQVAorCisJ
CWxvZHN3CQkJOyBMZW5ndGggb2Ygb3VyIERQVAorCQltb3YgY3gsW2VzOmRpXQorCQljbXAgY3gs
MjYJCTsgTWluaW11bSBzaXplCisJCWpiIC5vdmVycnVuCisKKwkJY21wIGN4LGF4CisJCWpiIC5v
a3NpemUKKwkJbW92IGN4LGF4CisKKy5va3NpemU6CisJCW1vdiBheCxjeAorCQlzdG9zdworCQlk
ZWMgY3gKKwkJZGVjIGN4CisJCXJlcCBtb3ZzYgorCisJCXhvciBheCxheAorCQlyZXQKKworLm92
ZXJydW46CisJCW1vdiBheCwwMTAwaAorCQlyZXQKKyVlbmRpZiA7IEVERAorCisJCTsgU2V0IHVw
IHJlZ2lzdGVycyBhcyBmb3IgYSAiUmVhZCIsIGFuZCBjb21wYXJlcyBhZ2FpbnN0IGRpc2sgc2l6
ZS4KKwkJOyBXQVJOSU5HOiBUaGlzIGZhaWxzIGltbWVkaWF0ZWx5LCBldmVuIGlmIHdlIGNhbiB0
cmFuc2ZlciBzb21lCisJCTsgc2VjdG9ycy4gIFRoaXMgaXNuJ3QgcmVhbGx5IHRoZSBjb3JyZWN0
IGJlaGF2aW91ci4KK3NldHVwX3JlZ3M6CisKKwkJOyBDb252ZXJ0IGEgQ0hTIGFkZHJlc3MgaW4g
UF9DWC9QX0RIIGludG8gYW4gTEJBIGluIGVheAorCQk7IENIID0gY3lsWzc6MF0KKwkJOyBDTFsw
OjVdID0gc2VjdG9yICgxLWJhc2VkKSAgQ0xbNzo2XSA9IGN5bFs5OjhdCisJCTsgREggPSBoZWFk
CisJCW1vdnp4IGVjeCxQX0NYCisJCW1vdnp4IGVieCxjbAkJOyBTZWN0b3IgbnVtYmVyCisJCWFu
ZCBibCwzRmgKKwkJZGVjIGVieAkJCTsgU2VjdG9yIG51bWJlciBpcyAxLWJhc2VkCisJCWNtcCBi
eCxbU2VjdG9yc10KKwkJamFlIC5vdmVycnVuCisJCW1vdnp4IGVkaSxQX0RICQk7IEhlYWQgbnVt
YmVyCisJCW1vdnp4IGVheCx3b3JkIFtIZWFkc10KKwkJY21wIGRpLGF4CisJCWphZSAub3ZlcnJ1
bgorCQlzaHIgY2wsNgorCQl4Y2hnIGNsLGNoCQk7IE5vdyAoRSlDWCA8LSBjeWxpbmRlciBudW1i
ZXIKKwkJbXVsIGVjeAkJCTsgZWF4IDwtIEhlYWRzKmN5bCMgKGVkeCA8LSAwKQorCQlhZGQgZWF4
LGVkaQorCQltdWwgZHdvcmQgW1NlY3RvcnNdCisJCWFkZCBlYXgsZWJ4CisJCTsgTm93IGVheCA9
IExCQSwgZWR4ID0gMAorCisJCTsKKwkJOyBzZXR1cF9yZWdzIGNvbnRpbnVlcy4uLgorCQk7CisJ
CTsgTm90ZTogZWRpWzMxOjE2XSBhbmQgZWN4WzMxOjE2XSA9IDAgYWxyZWFkeQorCQltb3YgZGks
UF9CWAkJOyBHZXQgbGluZWFyIGFkZHJlc3Mgb2YgdGFyZ2V0IGJ1ZmZlcgorCQltb3YgY3gsUF9F
UworCQlzaGwgZWN4LDQKKwkJYWRkIGVkaSxlY3gJCTsgRURJID0gYWRkcmVzcyB0byBmZXRjaCB0
bworCQltb3Z6eCBlY3gsUF9BTAkJOyBTZWN0b3IgY291bnQKKwkJbW92IGVzaSxlYXgKKwkJYWRk
IGVheCxlY3gJCTsgTEJBIG9mIGZpbmFsIHNlY3RvciArIDEKKwkJc2hsIGVzaSxTRUNUT1JTSVpF
X0xHMgk7IExCQSAtPiBieXRlIG9mZnNldAorCQlhZGQgZXNpLFtEaXNrQnVmXQk7IEdldCBhZGRy
ZXNzIGluIGhpZ2ggbWVtb3J5CisJCWNtcCBlYXgsW0Rpc2tTaXplXQk7IENoZWNrIHRoZSBoaWdo
IG1hcmsgYWdhaW5zdCBsaW1pdAorCQlqYSAub3ZlcnJ1bgorCQlzaGwgZWN4LFNFQ1RPUlNJWkVf
TEcyLTIgOyBDb252ZXJ0IGNvdW50IHRvIGR3b3JkcworCQlyZXQKKworLm92ZXJydW46CXBvcCBh
eAkJCTsgRHJvcCBzZXR1cF9yZWdzIHJldHVybiBhZGRyZXNzCisJCW1vdiBheCwwMjAwaAkJOyBN
aXNzaW5nIGFkZHJlc3MgbWFyaworCQlyZXQJCQk7IFJldHVybiB0byBEb25lCisKKwkJOyBTZXQg
dXAgcmVnaXN0ZXJzIGFzIGZvciBhbiBFREQgUmVhZCwgYW5kIGNvbXBhcmVzIGFnYWluc3QgZGlz
ayBzaXplLgorJWlmIEVERAorZWRkX3NldHVwX3JlZ3M6CisJCXB1c2ggZXMKKwkJbW92IHNpLFBf
U0kJCTsgRFM6U0kgLT4gREFQQQorCQltb3YgZXMsUF9EUworCisJCW1vdiBkeCxbZXM6c2ldCisJ
CWNtcCBkeCwxNgorCQlqYiAuYmFkZGFwYQorCisJCWNtcCBkd29yZCBbZXM6c2krNF0sLTEKKwkJ
amUgLmxpbmVhcl9hZGRyZXNzCisKKwkJbW92enggZWJ4LHdvcmQgW2VzOnNpKzRdCTsgT2Zmc2V0
CisJCW1vdnp4IGVkaSx3b3JkIFtlczpzaSs2XQk7IFNlZ21lbnQKKwkJc2hsIGVkaSw0CisJCWFk
ZCBlYngsZWRpCisJCWptcCAuZ290X2FkZHJlc3MKKworLmxpbmVhcl9hZGRyZXNzOgorCQljbXAg
ZHgsMjQJCTsgTXVzdCBiZSBsYXJnZSBlbm91Z2ggdG8gaG9sZAorCQkJCQk7IGxpbmVhciBhZGRy
ZXNzCisJCWpiIC5iYWRkYXBhCisKKwkJY21wIGR3b3JkIFtlczpzaSsyMF0sMAk7ID4gNCBHQiBh
ZGRyZXNzZXMgbm90IHN1cHBvcnRlZAorCQltb3YgYXgsMDkwMGgJCTsgIkRhdGEgYm91bmRhcnkg
ZXJyb3IiIC0gYm9ndXMsIGJ1dAorCQkJCQk7IG5vIHJlYWxseSBiZXR0ZXIgY29kZSBhdmFpbGFi
bGUKKwkJam5lIC5lcnJvcgorCisJCW1vdiBlYngsW2VzOnNpKzE2XQorCisuZ290X2FkZHJlc3M6
CisJCWNtcCBkd29yZCBbZXM6c2krMTJdLDAJCTsgTEJBIHRvbyBsYXJnZT8KKwkJam5lIC5vdmVy
cnVuCisKKwkJbW92enggZWN4LCB3b3JkIFtlczpzaSsyXQk7IFNlY3RvcnMgdG8gdHJhbnNmZXIK
KwkJbW92IGVzaSxbZXM6c2krOF0JCTsgU3RhcnRpbmcgc2VjdG9yCisJCW1vdiBlYXgsZXNpCisJ
CWFkZCBlYXgsZWN4CisJCWpjIC5vdmVycnVuCisJCWNtcCBlYXgsW0Rpc2tTaXplXQorCQlqYSAu
b3ZlcnJ1bgorCisJCXNobCBlY3gsU0VDVE9SU0laRV9MRzItMgk7IENvbnZlcnQgdG8gZHdvcmRz
CisJCXNobCBlc2ksU0VDVE9SU0laRV9MRzIJCTsgQ29udmVydCB0byBhbiBvZmZzZXQKKwkJYWRk
IGVzaSxbRGlza0J1Zl0KKwkJbW92IGVkaSxlYngKKwkJcG9wIGVzCisJCXJldAorCisuYmFkZGFw
YToKKwkJbW92IGF4LDAxMDBoCQk7IEludmFsaWQgY29tbWFuZAorCQlwb3AgZXMKKwkJcG9wIGF4
CQkJOyBEcm9wIHNldHVwX3JlZ3MgcmV0dXJuIGFkZHJlc3MKKwkJcmV0CisKKy5vdmVycnVuOgor
CQltb3YgYXgsMDIwMGgJCTsgIkFkZHJlc3MgbWFyayBub3QgZm91bmQiID0KKwkJCQkJOyBMQkEg
YmV5b25kIGVuZCBvZiBkaXNrCisuZXJyb3I6CisJCWFuZCB3b3JkIFtlczpzaSsyXSwwCTsgTm8g
c2VjdG9ycyB0cmFuc2ZlcnJlZAorCQlwb3AgZXMKKwkJcG9wIGF4CisJCXJldAorCitFRERFamVj
dDoKKwkJbW92IGF4LDBCMjAwaAkJOyBWb2x1bWUgTm90IFJlbW92YWJsZQorCQlyZXQKKworJWVu
ZGlmIDsgRURECisKKworOworOyBJTlQgMTVoIGludGVyY2VwdCByb3V0aW5lcworOworaW50MTVf
ZTgyMDoKKwkJY21wIGVkeCw1MzRENDE1MGgJOyAiU01BUCIKKwkJam5lIG9sZGludDE1CisJCWNt
cCBlY3gsMjAJCTsgTmVlZCAyMCBieXRlcworCQlqYiBlcnI4NgorCQlwdXNoIGRzCisJCXB1c2gg
Y3MKKwkJcG9wIGRzCisJCXB1c2ggZWR4CQk7ICJTTUFQIgorCQlhbmQgZWJ4LGVieAorCQlqbmUg
LnJlbmV3CisJCW1vdiBlYngsRTgyMFRhYmxlCisucmVuZXc6CisJCWFkZCBieCwxNgkJOyBBZHZh
bmNlIHRvIG5leHQKKwkJbW92IGVheCxbYngtOF0JCTsgVHlwZQorCQlhbmQgZWF4LGVheAkJOyBO
dWxsIHR5cGU/CisJCWp6IC5yZW5ldwkJOyBJZiBzbyBhZHZhbmNlIHRvIG5leHQKKwkJbW92IFtl
czpkaSsxNl0sZWF4CisJCWFuZCBjbCx+MworCQljbXAgZWN4LDI0CisJCWpiIC5ub19leHRhdHRy
CisJCW1vdiBlYXgsW2J4LTRdCQk7IEV4dGVuZGVkIGF0dHJpYnV0ZXMKKwkJbW92IFtlczpkaSsy
MF0sZWF4CisJCW1vdiBlY3gsMjQJCTsgQnl0ZXMgbG9hZGVkCisubm9fZXh0YXR0cjoKKwkJbW92
IGVheCxbYngtMTZdCQk7IFN0YXJ0IGFkZHIgKGxvdykKKwkJbW92IGVkeCxbYngtMTJdCQk7IFN0
YXJ0IGFkZHIgKGhpZ2gpCisJCW1vdiBbZXM6ZGldLGVheAorCQltb3YgW2VzOmRpKzRdLGVkeAor
CQltb3YgZWF4LFtieF0JCTsgRW5kIGFkZHIgKGxvdykKKwkJbW92IGVkeCxbYngrNF0JCTsgRW5k
IGFkZHIgKGhpZ2gpCisJCXN1YiBlYXgsW2J4LTE2XQkJOyBEZXJpdmUgdGhlIGxlbmd0aAorCQlz
YmIgZWR4LFtieC0xMl0KKwkJbW92IFtlczpkaSs4XSxlYXgJOyBMZW5ndGggKGxvdykKKwkJbW92
IFtlczpkaSsxMl0sZWR4CTsgTGVuZ3RoIChoaWdoKQorCQljbXAgZHdvcmQgW2J4KzhdLC0xCTsg
VHlwZSBvZiBuZXh0ID0gZW5kPworCQlqbmUgLm5vdGRvbmUKKwkJeG9yIGVieCxlYngJCTsgRG9u
ZSB3aXRoIHRhYmxlCisubm90ZG9uZToKKwkJcG9wIGVheAkJCTsgIlNNQVAiCisJCW1vdiBlZHgs
ZWF4CQk7IFNvbWUgc3lzdGVtcyBleHBlY3QgZWF4ID0gZWR4ID0gU01BUAorCQlwb3AgZHMKK2lu
dDE1X3N1Y2Nlc3M6CisJCW1vdiBieXRlIFticCs2XSwgMDJoCTsgQ2xlYXIgQ0YKKwkJcG9wIGJw
CisJCWlyZXQKKworZXJyODY6CisJCW1vdiBieXRlIFticCs2XSwgMDNoCTsgU2V0IENGCisJCW1v
diBhaCw4NmgKKwkJcG9wIGJwCisJCWlyZXQKKworSW50MTVTdGFydDoKKwkJcHVzaCBicAorCQlt
b3YgYnAsc3AKKwkJY21wIGF4LDBFODIwaAorCQlqZSBuZWFyIGludDE1X2U4MjAKKwkJY21wIGF4
LDBFODAxaAorCQlqZSBpbnQxNV9lODAxCisJCWNtcCBheCwwRTg4MWgKKwkJamUgaW50MTVfZTg4
MQorCQljbXAgYWgsODhoCisJCWplIGludDE1Xzg4CitvbGRpbnQxNToJcG9wIGJwCisJCWptcCBm
YXIgW2NzOk9sZEludDE1XQorCitpbnQxNV9lODAxOgorCQltb3YgYXgsW2NzOk1lbTFNQl0KKwkJ
bW92IGN4LGF4CisJCW1vdiBieCxbY3M6TWVtMTZNQl0KKwkJbW92IGR4LGJ4CisJCWptcCBzaG9y
dCBpbnQxNV9zdWNjZXNzCisKK2ludDE1X2U4ODE6CisJCW1vdiBlYXgsW2NzOk1lbTFNQl0KKwkJ
bW92IGVjeCxlYXgKKwkJbW92IGVieCxbY3M6TWVtMTZNQl0KKwkJbW92IGVkeCxlYngKKwkJam1w
IHNob3J0IGludDE1X3N1Y2Nlc3MKKworaW50MTVfODg6CisJCW1vdiBheCxbY3M6TWVtSW50MTU4
OF0KKwkJam1wIHNob3J0IGludDE1X3N1Y2Nlc3MKKworOworOyBSb3V0aW5lIHRvIGNvcHkgaW4v
b3V0IG9mIGhpZ2ggbWVtb3J5Cis7IGVzaSA9IGxpbmVhciBzb3VyY2UgYWRkcmVzcworOyBlZGkg
PSBsaW5lYXIgdGFyZ2V0IGFkZHJlc3MKKzsgZWN4ID0gMzItYml0IHdvcmQgY291bnQKKzsKKzsg
QXNzdW1lcyBjcyA9IGRzID0gZXMKKzsKK2Jjb3B5OgorCQlwdXNoIGVheAorCQlwdXNoIGVieAor
CQlwdXNoIGVkeAorCQlwdXNoIGVicAorCisJCW1vdiBieCwgcmVhbF9pbnQxNV9zdHViCisKKwkJ
dGVzdCBieXRlIFtDb25maWdGbGFnc10sIENPTkZJR19SQVd8Q09ORklHX1NBRkVJTlQKKwkJanog
LmFueW1vZGUJCTsgQWx3YXlzIGRvIHRoZSByZWFsIElOVCAxNWgKKworCQlzbXN3IGF4CQkJOyBV
bnByaXZpbGVnZWQhCisJCXRlc3QgYWwsMDFoCisJCWpueiAucHJvdG1vZGUJCTsgUHJvdG1vZGUg
LT4gZG8gcmVhbCBJTlQgMTVoCisKKy5yZWFsbW9kZToKKwkJOyBSYXcgb3IgU2FmZWludCBtb2Rl
LCBhbmQgd2UncmUgaW4gcmVhbCBtb2RlLi4uCisKKwkJdGVzdCBieXRlIFtDb25maWdGbGFnc10s
IENPTkZJR19TQUZFSU5UCisJCWpueiAuZmFrZWludDE1CisKKy5yYXc6CisJCVRSQUNFUiAncicK
KwkJOyBXZSdyZSBpbiByZWFsIG1vZGUsIGRvIGl0IG91dHNlbHZlcworCisJCXB1c2hmZAkJCTsg
PEE+CisJCXB1c2ggZHMJCQk7IDxCPgorCQlwdXNoIGVzCQkJOyA8Qz4KKworCQljbGkKKwkJY2xk
CisKKwkJeG9yIGVieCxlYngKKwkJbW92IGJ4LGNzCisJCXNobCBlYngsNAorCQlsZWEgZWR4LFtT
aGFrZXIrZWJ4XQorCQltb3YgW1NoYWtlcisyXSxlZHgKKworCQk7IFRlc3QgdG8gc2VlIGlmIEEy
MCBpcyBlbmFibGVkIG9yIG5vdAorCQl4b3IgYXgsYXgKKwkJbW92IGRzLGF4CisJCWRlYyBheAor
CQltb3YgZXMsYXgKKworCQltb3YgYXgsWzBdCisJCW1vdiBieCxheAorCQl4b3IgYngsW2VzOjEw
aF0KKwkJbm90IGF4CisJCW1vdiBbMF0sYXgKKwkJbW92IGR4LGF4CisJCXhvciBkeCxbZXM6MTBo
XQorCQlub3QgYXgKKwkJbW92IFswXSxheAorCisJCW9yIGR4LGJ4CisJCXB1c2ggZHgJCQk7IDxE
PiBTYXZlIEEyMCBzdGF0dXMKKwkJam56IC5za2lwX2EyMGUKKworCQltb3YgYXgsMjQwMWgJCTsg
RW5hYmxlIEEyMAorCQlpbnQgMTVoCisuc2tpcF9hMjBlOgorCQltb3YgZGwsW0NvbmZpZ0ZsYWdz
XQorCQlhbmQgZHgsQ09ORklHX0JJR1JBVworCQlhZGQgZHgsOAorCQk7IERYID0gMTYgZm9yIEJJ
R1JBVywgOCBmb3IgUkFXCisJCTsgIDggaXMgc2VsZWN0b3IgZm9yIGEgNjRLIGZsYXQgc2VnbWVu
dCwKKwkJOyAxNiBpcyBzZWxlY3RvciBmb3IgYSA0R0IgZmxhdCBzZWdtZW50LgorCisJCWxnZHQg
W2NzOlNoYWtlcl0KKwkJbW92IGVheCxjcjAKKwkJb3IgYWwsMDFoCisJCW1vdiBjcjAsZWF4CisK
KwkJbW92IGJ4LDE2CQk7IExhcmdlIGZsYXQgc2VnbWVudAorCQltb3YgZHMsYngKKwkJbW92IGVz
LGJ4CisKKwkJYTMyIHJlcCBtb3ZzZAorCisJCTsgRFggaGFzIHRoZSBhcHByb3ByaWF0ZSB2YWx1
ZSB0byBwdXQgaW4KKwkJOyB0aGUgcmVnaXN0ZXJzIG9uIHJldHVybgorCQltb3YgZHMsZHgKKwkJ
bW92IGVzLGR4CisKKwkJYW5kIGFsLH4wMWgKKwkJbW92IGNyMCxlYXgKKworCQlwb3AgZHgJCQk7
IDxEPiBBMjAgc3RhdHVzCisJCXBvcCBlcwkJCTsgPEM+CisJCXBvcCBkcwkJCTsgPEI+CisKKwkJ
YW5kIGR4LGR4CisJCWpueiAuc2tpcF9hMjBkCisJCW1vdiBheCwyNDAwaAkJOyBEaXNhYmxlIEEy
MAorCQlpbnQgMTVoCisuc2tpcF9hMjBkOgorCQlwb3BmZAkJCTsgPEE+CisJCWptcCAuZG9uZQor
CisuZmFrZWludDE1OgorCQk7IFdlJ3JlIGluIHJlYWwgbW9kZSB3aXRoIENPTkZJR19TQUZFSU5U
LCBpbnZva2UgdGhlCisJCTsgb3JpZ2luYWwgSU5UIDE1aCB2ZWN0b3IuICBXZSB1c2VkIHRvIHRl
c3QgZm9yIHRoZQorCQk7IElOVCAxNWggdmVjdG9yIGJlaW5nIHVuY2hhbmdlZCBoZXJlLCBidXQg
dGhhdCBpcworCQk7ICp1cyo7IGhvd2V2ZXIsIHRoZSB0ZXN0IHdhcyB3cm9uZyBmb3IgeWVhcnMg
KGFsd2F5cworCQk7IG5lZ2F0aXZlKSBzbyBpbnN0ZWFkIG9mIGZpeGluZyB0aGUgdGVzdCBkbyB3
aGF0IHdlCisJCTsgdGVzdGVkIGFuZCBkb24ndCBib3RoZXIgcHJvYmluZy4KKwkJbW92IGJ4LCBm
YWtlX2ludDE1X3N0dWIKKworLnByb3Rtb2RlOgorCQlUUkFDRVIgJ3AnCisuYW55bW9kZToKKwor
LmNvcHlfbG9vcDoKKwkJcHVzaCBlc2kKKwkJcHVzaCBlZGkKKwkJcHVzaCBlY3gKKwkJY21wIGVj
eCw0MDAwaAorCQlqbmEgLnNhZmVfc2l6ZQorCQltb3YgZWN4LDQwMDBoCisuc2FmZV9zaXplOgor
CQlwdXNoIGVjeAk7IFRyYW5zZmVyIHNpemUgdGhpcyBjeWNsZQorCQltb3YgZWF4LCBlc2kKKwkJ
bW92IFtNb3Zlcl9zcmMxXSwgc2kKKwkJc2hyIGVheCwgMTYKKwkJbW92IFtNb3Zlcl9zcmMxKzJd
LCBhbAorCQltb3YgW01vdmVyX3NyYzJdLCBhaAorCQltb3YgZWF4LCBlZGkKKwkJbW92IFtNb3Zl
cl9kc3QxXSwgZGkKKwkJc2hyIGVheCwgMTYKKwkJbW92IFtNb3Zlcl9kc3QxKzJdLCBhbAorCQlt
b3YgW01vdmVyX2RzdDJdLCBhaAorCQltb3Ygc2ksTW92ZXIKKwkJbW92IGFoLCA4N2gKKwkJc2hs
IGN4LDEJOyBDb252ZXJ0IHRvIDE2LWJpdCB3b3JkcworCQljYWxsIGJ4CQk7IElOVCAxNWggc3R1
YgorCQlwb3AgZWF4CQk7IFRyYW5zZmVyIHNpemUgdGhpcyBjeWNsZQorCQlwb3AgZWN4CisJCXBv
cCBlZGkKKwkJcG9wIGVzaQorCQlqYyAuZXJyb3IKKwkJbGVhIGVzaSxbZXNpKzQqZWF4XQorCQls
ZWEgZWRpLFtlZGkrNCplYXhdCisJCXN1YiBlY3gsIGVheAorCQlqbnogLmNvcHlfbG9vcAorCQk7
IENGID0gMAorLmVycm9yOgorLmRvbmU6CisJCXBvcCBlYnAKKwkJcG9wIGVkeAorCQlwb3AgZWJ4
CisJCXBvcCBlYXgKKwkJcmV0CisKK3JlYWxfaW50MTVfc3R1YjoKKwkJaW50IDE1aAorCQljbGkJ
CTsgU29tZSBCSU9TZXMgZW5hYmxlIGludGVycnVwdHMgb24gSU5UIDE1aAorCQlyZXQKKworZmFr
ZV9pbnQxNV9zdHViOgorCQlwdXNoZgorCQljYWxsIGZhciBbT2xkSW50MTVdCisJCWNsaQorCQly
ZXQKKworJWlmZGVmIERFQlVHX1RSQUNFUlMKK2RlYnVnX3RyYWNlcjoJcHVzaGFkCisJCXB1c2hm
ZAorCQltb3YgYnAsc3AKKwkJbW92IGJ4LFticCs5KjRdCisJCW1vdiBhbCxbY3M6YnhdCisJCWlu
YyB3b3JkIFticCs5KjRdCisJCW1vdiBhaCwwRWgKKwkJbW92IGJ4LDcKKwkJaW50IDEwaAorCQlw
b3BmZAorCQlwb3BhZAorCQlyZXQKKyVlbmRpZgorCisJCXNlY3Rpb24gLmRhdGEKKwkJYWxpZ25i
IDIKK0ludDEzRnVuY3MJZHcgUmVzZXQJCTsgMDBoIC0gUkVTRVQKKwkJZHcgR2V0U3RhdHVzCQk7
IDAxaCAtIEdFVCBTVEFUVVMKKwkJZHcgUmVhZAkJCTsgMDJoIC0gUkVBRAorCQlkdyBXcml0ZQkJ
OyAwM2ggLSBXUklURQorCQlkdyBWZXJpZnkJCTsgMDRoIC0gVkVSSUZZCisJCWR3IEludmFsaWQJ
CTsgMDVoIC0gRk9STUFUIFRSQUNLCisJCWR3IEludmFsaWQJCTsgMDZoIC0gRk9STUFUIFRSQUNL
IEFORCBTRVQgQkFEIEZMQUdTCisJCWR3IEludmFsaWQJCTsgMDdoIC0gRk9STUFUIERSSVZFIEFU
IFRSQUNLCisJCWR3IEdldFBhcm1zCQk7IDA4aCAtIEdFVCBQQVJBTUVURVJTCisJCWR3IEluaXRX
aXRoUGFybXMJOyAwOWggLSBJTklUSUFMSVpFIENPTlRST0xMRVIgV0lUSCBEUklWRSBQQVJBTUVU
RVJTCisJCWR3IEludmFsaWQJCTsgMEFoCisJCWR3IEludmFsaWQJCTsgMEJoCisJCWR3IFNlZWsJ
CQk7IDBDaCAtIFNFRUsgVE8gQ1lMSU5ERVIKKwkJZHcgUmVzZXQJCTsgMERoIC0gUkVTRVQgSEFS
RCBESVNLUworCQlkdyBJbnZhbGlkCQk7IDBFaAorCQlkdyBJbnZhbGlkCQk7IDBGaAorCQlkdyBD
aGVja0lmUmVhZHkJCTsgMTBoIC0gQ0hFQ0sgSUYgUkVBRFkKKwkJZHcgUmVjYWxpYnJhdGUJCTsg
MTFoIC0gUkVDQUxJQlJBVEUKKwkJZHcgSW52YWxpZAkJOyAxMmgKKwkJZHcgSW52YWxpZAkJOyAx
M2gKKwkJZHcgSW52YWxpZAkJOyAxNGgKKwkJZHcgR2V0RHJpdmVUeXBlCQk7IDE1aCAtIEdFVCBE
UklWRSBUWVBFCisJCWR3IERldGVjdENoYW5nZQkJOyAxNmggLSBERVRFQ1QgRFJJVkUgQ0hBTkdF
CislaWYgRURECisJCWR3IEludmFsaWQJCTsgMTdoCisJCWR3IEludmFsaWQJCTsgMThoCisJCWR3
IEludmFsaWQJCTsgMTloCisJCWR3IEludmFsaWQJCTsgMUFoCisJCWR3IEludmFsaWQJCTsgMUJo
CisJCWR3IEludmFsaWQJCTsgMUNoCisJCWR3IEludmFsaWQJCTsgMURoCisJCWR3IEludmFsaWQJ
CTsgMUVoCisJCWR3IEludmFsaWQJCTsgMUZoCisJCWR3IEludmFsaWQJCTsgMjBoCisJCWR3IFJl
YWRNdWx0CQk7IDIxaCAtIFJFQUQgTVVMVElQTEUKKwkJZHcgV3JpdGVNdWx0CQk7IDIyaCAtIFdS
SVRFIE1VTFRJUExFCisJCWR3IFNldE1vZGUJCTsgMjNoIC0gU0VUIENPTlRST0xMRVIgRkVBVFVS
RVMKKwkJZHcgU2V0TW9kZQkJOyAyNGggLSBTRVQgTVVMVElQTEUgTU9ERQorCQlkdyBJbnZhbGlk
CQk7IDI1aCAtIElERU5USUZZIERSSVZFCisJCWR3IEludmFsaWQJCTsgMjZoCisJCWR3IEludmFs
aWQJCTsgMjdoCisJCWR3IEludmFsaWQJCTsgMjhoCisJCWR3IEludmFsaWQJCTsgMjloCisJCWR3
IEludmFsaWQJCTsgMkFoCisJCWR3IEludmFsaWQJCTsgMkJoCisJCWR3IEludmFsaWQJCTsgMkNo
CisJCWR3IEludmFsaWQJCTsgMkRoCisJCWR3IEludmFsaWQJCTsgMkVoCisJCWR3IEludmFsaWQJ
CTsgMkZoCisJCWR3IEludmFsaWQJCTsgMzBoCisJCWR3IEludmFsaWQJCTsgMzFoCisJCWR3IElu
dmFsaWQJCTsgMzJoCisJCWR3IEludmFsaWQJCTsgMzNoCisJCWR3IEludmFsaWQJCTsgMzRoCisJ
CWR3IEludmFsaWQJCTsgMzVoCisJCWR3IEludmFsaWQJCTsgMzZoCisJCWR3IEludmFsaWQJCTsg
MzdoCisJCWR3IEludmFsaWQJCTsgMzhoCisJCWR3IEludmFsaWQJCTsgMzloCisJCWR3IEludmFs
aWQJCTsgM0FoCisJCWR3IEludmFsaWQJCTsgM0JoCisJCWR3IEludmFsaWQJCTsgM0NoCisJCWR3
IEludmFsaWQJCTsgM0RoCisJCWR3IEludmFsaWQJCTsgM0VoCisJCWR3IEludmFsaWQJCTsgM0Zo
CisJCWR3IEludmFsaWQJCTsgNDBoCisJCWR3IEVERFByZXNlbmNlCQk7IDQxaCAtIEVERCBQUkVT
RU5DRSBERVRFQ1QKKwkJZHcgRUREUmVhZAkJOyA0MmggLSBFREQgUkVBRAorCQlkdyBFRERXcml0
ZQkJOyA0M2ggLSBFREQgV1JJVEUKKwkJZHcgRUREVmVyaWZ5CQk7IDQ0aCAtIEVERCBWRVJJRlkK
KwkJZHcgRURETG9jawkJOyA0NWggLSBFREQgTE9DSy9VTkxPQ0sgTUVESUEKKwkJZHcgRURERWpl
Y3QJCTsgNDZoIC0gRUREIEVKRUNUCisJCWR3IEVERFNlZWsJCTsgNDdoIC0gRUREIFNFRUsKKwkJ
ZHcgRURER2V0UGFybXMJCTsgNDhoIC0gRUREIEdFVCBQQVJBTUVURVJTCisJCWR3IEVERERldGVj
dENoYW5nZQk7IDQ5aCAtIEVERCBNRURJQSBDSEFOR0UgU1RBVFVTCislZW5kaWYKKworSW50MTNG
dW5jc0VuZAllcXUgJAorSW50MTNGdW5jc0NudAllcXUgKEludDEzRnVuY3NFbmQtSW50MTNGdW5j
cykgPj4gMQorCisKKwkJYWxpZ25iIDgsIGRiIDAKK1NoYWtlcgkJZHcgU2hha2VyRW5kLSQKKwkJ
ZGQgMAkJCTsgUG9pbnRlciB0byBzZWxmCisJCWR3IDAKKworU2hha2VyX1JNRFM6CWRkIDB4MDAw
MGZmZmYJCTsgNjRLIGRhdGEgc2VnbWVudAorCQlkZCAweDAwMDA5MzAwCisKK1NoYWtlcl9EUzoJ
ZGQgMHgwMDAwZmZmZgkJOyA0R0IgZGF0YSBzZWdtZW50CisJCWRkIDB4MDA4ZjkzMDAKKworU2hh
a2VyRW5kCWVxdSAkCisKKwkJYWxpZ25iIDgsIGRiIDAKKworTW92ZXIJCWRkIDAsIDAsIDAsIDAJ
CTsgTXVzdCBiZSB6ZXJvCisJCWR3IDBmZmZmaAkJOyA2NCBLIHNlZ21lbnQgc2l6ZQorTW92ZXJf
c3JjMToJZGIgMCwgMCwgMAkJOyBMb3cgMjQgYml0cyBvZiBzb3VyY2UgYWRkeQorCQlkYiA5M2gJ
CQk7IEFjY2VzcyByaWdodHMKKwkJZGIgMDBoCQkJOyBFeHRlbmRlZCBhY2Nlc3MgcmlnaHRzCitN
b3Zlcl9zcmMyOglkYiAwCQkJOyBIaWdoIDggYml0cyBvZiBzb3VyY2UgYWRkeQorCQlkdyAwZmZm
ZmgJCTsgNjQgSyBzZWdtZW50IHNpemUKK01vdmVyX2RzdDE6CWRiIDAsIDAsIDAJCTsgTG93IDI0
IGJpdHMgb2YgdGFyZ2V0IGFkZHkKKwkJZGIgOTNoCQkJOyBBY2Nlc3MgcmlnaHRzCisJCWRiIDAw
aAkJCTsgRXh0ZW5kZWQgYWNjZXNzIHJpZ2h0cworTW92ZXJfZHN0MjoJZGIgMAkJCTsgSGlnaCA4
IGJpdHMgb2Ygc291cmNlIGFkZHkKK01vdmVyX2R1bW15MjoJZGQgMCwgMCwgMCwgMAkJOyBNb3Jl
IHNwYWNlIGZvciB0aGUgQklPUworCisJCWFsaWduYiA0LCBkYiAwCitNZW1EaXNrX0luZm8JZXF1
ICQJCQk7IFBvaW50ZWQgdG8gYnkgaW5zdGFsbGF0aW9uIGNoZWNrCitNRElfQnl0ZXMJZHcgTURJ
X0xlbgkJOyBUb3RhbCBieXRlcyBpbiBNREkgc3RydWN0dXJlCitNRElfVmVyc2lvbglkYiBWRVJT
SU9OX01JTk9SLCBWRVJTSU9OX01BSk9SCTsgTUVNRElTSyB2ZXJzaW9uCisKK1BhdGNoQXJlYQll
cXUgJAkJCTsgVGhpcyBnZXRzIGZpbGxlZCBpbiBieSB0aGUgaW5zdGFsbGVyCisKK0Rpc2tCdWYJ
CWRkIDAJCQk7IExpbmVhciBhZGRyZXNzIG9mIGhpZ2ggbWVtb3J5IGRpc2sKK0Rpc2tTaXplCWRk
IDAJCQk7IFNpemUgb2YgZGlzayBpbiBibG9ja3MKK0NvbW1hbmRMaW5lCWR3IDAsIDAJCQk7IEZh
ciBwb2ludGVyIHRvIHNhdmVkIGNvbW1hbmQgbGluZQorCitPbGRJbnQxMwlkZCAwCQkJOyBJTlQg
MTNoIGluIGNoYWluCitPbGRJbnQxNQlkZCAwCQkJOyBJTlQgMTVoIGluIGNoYWluCisKK09sZERv
c01lbQlkdyAwCQkJOyBPbGQgcG9zaXRpb24gb2YgRE9TIG1lbSBlbmQKK0Jvb3RMb2FkZXJJRAlk
YiAwCQkJOyBCb290IGxvYWRlciBJRCBmcm9tIGhlYWRlcgorCQlkYiAwCQkJOyBwYWQKKworRFBU
X3B0cgkJZHcgMAkJCTsgSWYgbm9uemVybywgcG9pbnRlciB0byBEUFQKKwkJCQkJOyBPcmlnaW5h
bCBEUFQgcG9pbnRlciBmb2xsb3dzCisKK01ESV9MZW4JCWVxdSAkLU1lbURpc2tfSW5mbworCis7
IC0tLS0gTURJIHN0cnVjdHVyZSBlbmRzIGhlcmUgLS0tCitJbnQxM01heEZ1bmMJZGIgSW50MTNG
dW5jc0NudC0xCTsgTWF4IElOVCAxM2ggZnVuY3Rpb24gKHRvIGRpc2FibGUgRUREKQorCQlkYiAw
CQkJOyBwYWQKKworCQlkdyAwCQkJOyBwYWQKK01lbUludDE1ODgJZHcgMAkJCTsgMU1CLTY1TUIg
bWVtb3J5IGFtb3VudCAoMUspCisKK0N5bGluZGVycwlkdyAwCQkJOyBDeWxpbmRlciBjb3VudAor
SGVhZHMJCWR3IDAJCQk7IEhlYWQgY291bnQKK1NlY3RvcnMJCWRkIDAJCQk7IFNlY3RvciBjb3Vu
dCAoemVyby1leHRlbmRlZCkKKworTWVtMU1CCQlkZCAwCQkJOyAxTUItMTZNQiBtZW1vcnkgYW1v
dW50ICgxSykKK01lbTE2TUIJCWRkIDAJCQk7IDE2TUItNEcgbWVtb3J5IGFtb3VudCAoNjRLKQor
CitEcml2ZU5vCQlkYiAwCQkJOyBPdXIgZHJpdmUgbnVtYmVyCitEcml2ZVR5cGUJZGIgMAkJCTsg
T3VyIGRyaXZlIHR5cGUgKGZsb3BwaWVzKQorRHJpdmVDbnQJZGIgMAkJCTsgRHJpdmUgY291bnQg
KGZyb20gdGhlIEJJT1MpCisKK0NvbmZpZ0ZsYWdzCWRiIDAJCQk7IEJpdCAwIC0gcmVhZG9ubHkK
KworTXlTdGFjawkJZHcgMAkJCTsgT2Zmc2V0IG9mIHN0YWNrCitTdGF0dXNQdHIJZHcgMAkJCTsg
V2hlcmUgdG8gc2F2ZSBzdGF0dXMgKHplcm9zZWcgcHRyKQorCitEUFQJCXRpbWVzIDE2IGRiIDAJ
CTsgQklPUyBwYXJhbWV0ZXIgdGFibGUgcG9pbnRlciAoZmxvcHBpZXMpCitPbGRJbnQxRQlkZCAw
CQkJOyBQcmV2aW91cyBJTlQgMUUgcG9pbnRlciAoRFBUKQorCislaWYgRURECitFRERfRFBUOgor
Lmxlbmd0aAkJZHcgMzAKKy5pbmZvCQlkdyAwMDI5aAorCQk7IEJpdCAwIC0gRE1BIGJvdW5kYXJp
ZXMgaGFuZGxlZCB0cmFuc3BhcmVudGx5CisJCTsgQml0IDMgLSBEZXZpY2Ugc3VwcG9ydHMgd3Jp
dGUgdmVyaWZ5CisJCTsgQml0IDUgLSBNZWRpYSBpcyBsb2NrYWJsZQorLmN5bGluZGVycwlkZCAw
CQkJOyBGaWxsZWQgaW4gYnkgaW5zdGFsbGVyCisuaGVhZHMJCWRkIDAJCQk7IEZpbGxlZCBpbiBi
eSBpbnN0YWxsZXIKKy5zZWN0b3JzCWRkIDAJCQk7IEZpbGxlZCBpbiBieSBpbnN0YWxsZXIKKy50
b3RhbHNpemUJZGQgMCwgMAkJCTsgRmlsbGVkIGluIGJ5IGluc3RhbGxlcgorLmJ5dGVzcGVyc2Vj
CWR3IFNFQ1RPUlNJWkUKKy5lZGR0YWJsZQlkdyAtMSwgLTEJCTsgSW52YWxpZCBEUFRFIHBvaW50
ZXIKKworJWVuZGlmCisKKwkJOyBFbmQgcGF0Y2ggYXJlYQorU3RhY2sJCWRkIDAJCQk7IFNhdmVk
IFNTOkVTUCBvbiBpbnZvY2F0aW9uCisJCWR3IDAKK1NhdmVkQVgJCWR3IDAJCQk7IEFYIHNhdmVk
IG9uIGludm9jYXRpb24KKworCQlhbGlnbmIgNCwgZGIgMAkJOyBXZSAqTVVTVCogZW5kIG9uIGEg
ZHdvcmQgYm91bmRhcnkKKworRTgyMFRhYmxlCWVxdSAkCQkJOyBUaGUgaW5zdGFsbGVyIGxvYWRz
IHRoZSBFODIwIHRhYmxlIGhlcmUKK1RvdGFsU2l6ZQllcXUgJAkJCTsgRW5kIHBvaW50ZXIKZGlm
ZiAtLWdpdCBhL21lbWRpc2svbWVtZGlza19lZGQuYXNtIGIvbWVtZGlzay9tZW1kaXNrX2VkZC5h
c20KbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uOTdkM2ZlOQotLS0gL2Rldi9u
dWxsCisrKyBiL21lbWRpc2svbWVtZGlza19lZGQuYXNtCkBAIC0wLDAgKzEsMiBAQAorJWRlZmlu
ZSBXSVRIX0VERAorJWluY2x1ZGUgIm1lbWRpc2suaW5jIgpkaWZmIC0tZ2l0IGEvbWVtZGlzay9z
ZXR1cC5jIGIvbWVtZGlzay9zZXR1cC5jCmluZGV4IDdiMWY0NTYuLmVkMDhkNTcgMTAwNjQ0Ci0t
LSBhL21lbWRpc2svc2V0dXAuYworKysgYi9tZW1kaXNrL3NldHVwLmMKQEAgLTI0LDYgKzI0LDkg
QEAgY29uc3QgY2hhciBjb3B5cmlnaHRbXSA9CiAKIGV4dGVybiBjb25zdCBjaGFyIF9iaW5hcnlf
bWVtZGlza19iaW5fc3RhcnRbXSwgX2JpbmFyeV9tZW1kaXNrX2Jpbl9lbmRbXTsKIGV4dGVybiBj
b25zdCBjaGFyIF9iaW5hcnlfbWVtZGlza19iaW5fc2l6ZVtdOyAvKiBXZWlyZCwgSSBrbm93ICov
CitleHRlcm4gY29uc3QgY2hhciBfYmluYXJ5X21lbWRpc2tfZWRkX2Jpbl9zdGFydFtdLAorICAg
ICAgIF9iaW5hcnlfbWVtZGlza19lZGRfZW5kW107CitleHRlcm4gY29uc3QgY2hhciBfYmluYXJ5
X21lbWRpc2tfZWRkX2Jpbl9zaXplW107CiAKIHN0cnVjdCBtZW1kaXNrX2hlYWRlciB7CiAgIHVp
bnQxNl90IGludDEzX29mZnM7CkBAIC05Myw3ICs5Niw2IEBAIHN0cnVjdCBwYXRjaF9hcmVhIHsK
ICAgdWludDE2X3QgZHB0X3B0cjsKICAgLyogRW5kIG9mIHRoZSBvZmZpY2lhbCBNZW1EaXNrX0lu
Zm8gKi8KICAgdWludDhfdCAgbWF4aW50MTNmdW5jOwotI2RlZmluZSBNQVhJTlQxM19OT0VERAkw
eDE2CiAgIHVpbnQ4X3QgIF9wYWQyOwogCiAgIHVpbnQxNl90IF9wYWQzOwpAQCAtNTk4LDcgKzYw
MCw4IEBAIHZvaWQgKnN5c19ib3VuY2U7CiAKIF9fY2RlY2wgdm9pZCBzZXR1cChfX2NkZWNsIHN5
c2NhbGxfdCBjc19zeXNjYWxsLCB2b2lkICpjc19ib3VuY2UpCiB7Ci0gIHVuc2lnbmVkIGludCBi
aW5fc2l6ZSA9IChpbnQpICZfYmluYXJ5X21lbWRpc2tfYmluX3NpemU7CisgIHVuc2lnbmVkIGlu
dCBiaW5fc2l6ZTsKKyAgY2hhciAqbWVtZGlza19ob29rOwogICBzdHJ1Y3QgbWVtZGlza19oZWFk
ZXIgKmhwdHI7CiAgIHN0cnVjdCBwYXRjaF9hcmVhICpwcHRyOwogICB1aW50MTZfdCBkcml2ZXJz
ZWc7CkBAIC02MTAsNyArNjEzLDcgQEAgX19jZGVjbCB2b2lkIHNldHVwKF9fY2RlY2wgc3lzY2Fs
bF90IGNzX3N5c2NhbGwsIHZvaWQgKmNzX2JvdW5jZSkKICAgY29tMzJzeXNfdCByZWdzOwogICB1
aW50MzJfdCByYW1kaXNrX2ltYWdlLCByYW1kaXNrX3NpemU7CiAgIGludCBiaW9zX2RyaXZlczsK
LSAgaW50IGRvX2VkZCA9IC0xOwkJLyogLTEgPSBkZWZhdWx0LCAwID0gbm8sIDEgPSB5ZXMgKi8K
KyAgaW50IGRvX2VkZCA9IDE7CQkvKiAwID0gbm8sIDEgPSB5ZXMsIGRlZmF1bHQgaXMgeWVzICov
CiAgIGludCBub19icHQ7CQkJLyogTm8gdmFsaWQgQlBUIHByZXNlbnRlZCAqLwogCiAgIC8qIFNl
dCB1cCBnbG9iYWwgdmFyaWFibGVzICovCkBAIC02NDksMTMgKzY1MiwyMiBAQCBfX2NkZWNsIHZv
aWQgc2V0dXAoX19jZGVjbCBzeXNjYWxsX3QgY3Nfc3lzY2FsbCwgdm9pZCAqY3NfYm91bmNlKQog
ICBlbHNlCiAgICAgZG9fZWRkID0gKGdlb21ldHJ5LT5kcml2ZW5vICYgMHg4MCkgPyAxIDogMDsK
IAorICAvKiBDaG9vc2UgdGhlIGFwcHJvcHJpYXRlIGluc3RhbGxhYmxlIG1lbWRpc2sgaG9vayAq
LworICBpZiAoZG9fZWRkKSB7CisgICAgYmluX3NpemUgPSAoaW50KSAmX2JpbmFyeV9tZW1kaXNr
X2VkZF9iaW5fc2l6ZTsKKyAgICBtZW1kaXNrX2hvb2sgPSAoY2hhciAqKSAmX2JpbmFyeV9tZW1k
aXNrX2VkZF9iaW5fc3RhcnQ7CisgIH0gZWxzZSB7CisgICAgYmluX3NpemUgPSAoaW50KSAmX2Jp
bmFyeV9tZW1kaXNrX2Jpbl9zaXplOworICAgIG1lbWRpc2tfaG9vayA9IChjaGFyICopICZfYmlu
YXJ5X21lbWRpc2tfYmluX3N0YXJ0OworICB9CisKICAgLyogUmVzZXJ2ZSB0aGUgcmFtZGlzayBt
ZW1vcnkgKi8KICAgaW5zZXJ0cmFuZ2UocmFtZGlza19pbWFnZSwgcmFtZGlza19zaXplLCAyLCAx
KTsKICAgcGFyc2VfbWVtKCk7CQkJLyogUmVjb21wdXRlIHZhcmlhYmxlcyAqLwogCiAgIC8qIEZp
Z3VyZSBvdXQgd2hlcmUgaXQgbmVlZHMgdG8gZ28gKi8KLSAgaHB0ciA9IChzdHJ1Y3QgbWVtZGlz
a19oZWFkZXIgKikgJl9iaW5hcnlfbWVtZGlza19iaW5fc3RhcnQ7Ci0gIHBwdHIgPSAoc3RydWN0
IHBhdGNoX2FyZWEgKikoX2JpbmFyeV9tZW1kaXNrX2Jpbl9zdGFydCArIGhwdHItPnBhdGNoX29m
ZnMpOworICBocHRyID0gKHN0cnVjdCBtZW1kaXNrX2hlYWRlciAqKSBtZW1kaXNrX2hvb2s7Cisg
IHBwdHIgPSAoc3RydWN0IHBhdGNoX2FyZWEgKikobWVtZGlza19ob29rICsgaHB0ci0+cGF0Y2hf
b2Zmcyk7CiAKICAgZG9zbWVtX2sgPSByZHpfMTYoQklPU19CQVNFTUVNKTsKICAgcHB0ci0+b2xk
ZG9zbWVtID0gZG9zbWVtX2s7CkBAIC03MjYsMTAgKzczOCw2IEBAIF9fY2RlY2wgdm9pZCBzZXR1
cChfX2NkZWNsIHN5c2NhbGxfdCBjc19zeXNjYWxsLCB2b2lkICpjc19ib3VuY2UpCiAgIH0KICAg
cHV0cygiIGFjY2VzcyB0byBoaWdoIG1lbW9yeVxuIik7CiAKLSAgLyogcHB0ci0+bWF4aW50MTNm
dW5jIGRlZmF1bHRzIHRvIEVERCBlbmFibGVkLCBpZiBjb21waWxlZCBpbiAqLwotICBpZiAoIWRv
X2VkZCkKLSAgICBwcHRyLT5tYXhpbnQxM2Z1bmMgPSBNQVhJTlQxM19OT0VERDsKLQogICAvKiBT
ZXQgdXAgYSBkcml2ZSBwYXJhbWV0ZXIgdGFibGUgKi8KICAgaWYgKCBnZW9tZXRyeS0+ZHJpdmVu
byAmIDB4ODAgKSB7CiAgICAgLyogSGFyZCBkaXNrICovCkBAIC04OTgsNyArOTA2LDcgQEAgX19j
ZGVjbCB2b2lkIHNldHVwKF9fY2RlY2wgc3lzY2FsbF90IGNzX3N5c2NhbGwsIHZvaWQgKmNzX2Jv
dW5jZSkKICAgICBocHRyID0gKHN0cnVjdCBtZW1kaXNrX2hlYWRlciAqKWRwcDsKIAogICAgIC8q
IEFjdHVhbGx5IGNvcHkgdG8gbG93IG1lbW9yeSAqLwotICAgIGRwcCA9IG1lbXBjcHkoZHBwLCAm
X2JpbmFyeV9tZW1kaXNrX2Jpbl9zdGFydCwgYmluX3NpemUpOworICAgIGRwcCA9IG1lbXBjcHko
ZHBwLCBtZW1kaXNrX2hvb2ssIGJpbl9zaXplKTsKICAgICBkcHAgPSBtZW1wY3B5KGRwcCwgcmFu
Z2VzLCAobnJhbmdlcysxKSpzaXplb2YocmFuZ2VzWzBdKSk7CiAgICAgZHBwID0gbWVtcGNweShk
cHAsIHNoZHItPmNtZGxpbmUsIGNtZGxpbmVsZW4rMSk7CiAgIH0KLS0gCjEuNS4zLjQKCg=
------_=_NextPart_001_01C9A06C.565F4677--