diff --git a/sys/elf64.pas b/sys/elf64.pas
index 69c753e3..f9c0a67a 100644
--- a/sys/elf64.pas
+++ b/sys/elf64.pas
@@ -397,6 +397,8 @@ const
SELF_PT_SECURE_MODULE=$E;
SELF_PT_SECURE_KERNEL=$F;
+ SELF_CONTROL_BLOCK_TYPE_NPDRM = $3;
+
type
p_self_segment=^t_self_segment;
t_self_segment=packed record
@@ -412,10 +414,17 @@ type
Program_Type :QWORD;
Program_Version:QWORD;
System_Version :QWORD;
- //Content_ID :array[0..31] of Byte; //Optional
Digest_SHA_256 :array[0..31] of Byte;
end;
+ p_self_npdrm_control_block=^t_self_npdrm_control_block;
+ t_self_npdrm_control_block=packed record
+ pType :Word;
+ Unknown :array[0..13] of byte;
+ ContentID:array[0..18] of byte;
+ RandomPad:array[0..12] of byte;
+ end;
+
p_eh_frame_hdr=^eh_frame_hdr;
eh_frame_hdr=packed record
version :Byte;
diff --git a/sys/jit/kern_jit.pas b/sys/jit/kern_jit.pas
index fb3e1d84..7693f98f 100644
--- a/sys/jit/kern_jit.pas
+++ b/sys/jit/kern_jit.pas
@@ -1020,6 +1020,9 @@ begin
vm_map_unlock(@g_vmspace.vm_map);
end;
+var
+ _print_stat:Integer=0;
+
procedure pick_locked(var ctx:t_jit_context2);
const
SCODES:array[TSimdOpcode] of Byte=(0,0,1,3,2);
@@ -1060,7 +1063,10 @@ begin
Writeln(' ctx.text___end:0x',HexStr(ctx.text___end,16));
Writeln(' ctx.map____end:0x',HexStr(ctx.map____end,16));
- print_test_jit_cbs(False,True);
+ if System.InterlockedExchange(_print_stat,1)=0 then
+ begin
+ print_test_jit_cbs(False,True);
+ end;
links:=Default(t_jit_context2.t_forward_links);
addr:=nil;
@@ -1091,7 +1097,7 @@ begin
goto _invalid;
end;
- if ((pmap_get_raw(QWORD(ptr)) and PAGE_PROT_EXECUTE)=0) then
+ if ((pmap_get_prot(QWORD(ptr)) and PAGE_PROT_EXECUTE)=0) then
begin
writeln('not excec:0x',HexStr(ptr));
goto _invalid;
diff --git a/sys/jit/kern_jit_asm.pas b/sys/jit/kern_jit_asm.pas
index f7fd620b..12138ae2 100644
--- a/sys/jit/kern_jit_asm.pas
+++ b/sys/jit/kern_jit_asm.pas
@@ -163,7 +163,7 @@ asm
add PAGE_MAP(%rip),%r14
mov (%r14),%r14d
//filter (r14)
- and PAGE_OFS_MASK,%r14
+ test %r14,%r14
jz _sigsegv
//combine (r14|rax)
shl PAGE_SHIFT,%r14
@@ -228,9 +228,6 @@ asm
mov (%rax,%rsi),%esi
//restore
mov - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rax(%r13) ,%rax
- //filter (rdi,rsi)
- and PAGE_OFS_MASK,%rdi
- and PAGE_OFS_MASK,%rsi
//
inc %rdi
cmp %rdi,%rsi
diff --git a/sys/jit/kern_jit_ctx.pas b/sys/jit/kern_jit_ctx.pas
index 050e295a..eb7416e6 100644
--- a/sys/jit/kern_jit_ctx.pas
+++ b/sys/jit/kern_jit_ctx.pas
@@ -845,13 +845,13 @@ begin
//jmp [addr]
if ctx.is_map_addr(ofs) then
- if ((pmap_get_raw(QWORD(ofs)) and PAGE_PROT_READ)<>0) then
+ if ((pmap_get_prot(QWORD(ofs)) and PAGE_PROT_READ)<>0) then
begin
ofs:=PInt64(ofs)^;
if ctx.is_text_addr(ofs) then
if (ctx.max=0) or (ofs<=ctx.max) then
- if ((pmap_get_raw(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then
+ if ((pmap_get_prot(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then
begin
ctx.add_forward_point(fpCall,Pointer(ofs));
end;
@@ -865,7 +865,7 @@ begin
if ctx.is_text_addr(ofs) then
begin
if (ofs<=ctx.max) then
- if ((pmap_get_raw(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then
+ if ((pmap_get_prot(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then
begin
ctx.add_forward_point(fpData,Pointer(ofs));
end;
diff --git a/sys/jit/kern_jit_dynamic.pas b/sys/jit/kern_jit_dynamic.pas
index 850eb03b..ef870ea2 100644
--- a/sys/jit/kern_jit_dynamic.pas
+++ b/sys/jit/kern_jit_dynamic.pas
@@ -156,7 +156,7 @@ begin
begin
Result:=addr;
- if ((pmap_get_raw(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then
+ if ((pmap_get_prot(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then
begin
Break;
end;
@@ -174,7 +174,7 @@ begin
begin
Result:=addr;
- if ((pmap_get_raw(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then
+ if ((pmap_get_prot(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then
begin
Break;
end;
@@ -397,7 +397,7 @@ begin
_start:
- if ((pmap_get_raw(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then
+ if ((pmap_get_prot(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then
begin
writeln('not excec:0x',HexStr(addr));
Assert(False,'TODO');
diff --git a/sys/kern/systm.pas b/sys/kern/systm.pas
index a0ff91bf..86187ee7 100644
--- a/sys/kern/systm.pas
+++ b/sys/kern/systm.pas
@@ -75,7 +75,7 @@ begin
guest:=is_guest_addr(QWORD(udaddr));
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)=0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)=0) then
begin
Result:=EFAULT;
goto _exit;
@@ -97,7 +97,7 @@ begin
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then
begin
goto _next;
end else
@@ -152,7 +152,7 @@ begin
guest:=is_guest_addr(QWORD(udaddr));
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)=0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)=0) then
begin
Result:=EFAULT;
goto _exit;
@@ -177,7 +177,7 @@ begin
begin
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then
begin
Result:=0;
end else
@@ -227,7 +227,7 @@ begin
guest:=is_guest_addr(QWORD(udaddr));
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)=0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)=0) then
begin
Result:=EFAULT;
goto _exit;
@@ -249,7 +249,7 @@ begin
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then
begin
goto _next;
end else
@@ -321,7 +321,7 @@ begin
guest:=is_guest_addr(QWORD(udaddr));
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then
begin
Result:=EFAULT;
goto _exit;
@@ -343,7 +343,7 @@ begin
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then
begin
goto _next;
end else
@@ -398,7 +398,7 @@ begin
guest:=is_guest_addr(QWORD(udaddr));
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then
begin
Result:=EFAULT;
goto _exit;
@@ -423,7 +423,7 @@ begin
begin
if guest then
begin
- if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then
+ if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then
begin
Result:=0;
end else
@@ -514,7 +514,7 @@ begin
_fault:
if guest then
begin
- if ((pmap_get_raw(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then
+ if ((pmap_get_prot(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then
begin
goto _begin;
end else
@@ -571,7 +571,7 @@ begin
_fault:
if guest then
begin
- if ((pmap_get_raw(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then
+ if ((pmap_get_prot(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then
begin
goto _begin;
end else
diff --git a/sys/md/vm_pmap.pas b/sys/md/vm_pmap.pas
index 0d2c2cec..ba360c25 100644
--- a/sys/md/vm_pmap.pas
+++ b/sys/md/vm_pmap.pas
@@ -16,26 +16,22 @@ const
PAGE_MAP_COUNT =(QWORD(VM_MAXUSER_ADDRESS) shr PAGE_SHIFT);
PAGE_MAP_MASK =PAGE_MAP_COUNT-1;
- PAGE_PROT_EXECUTE=DWORD($80000000);
- PAGE_PROT_WRITE =DWORD($40000000);
- PAGE_PROT_READ =DWORD($20000000);
+ PAGE_PROT_EXECUTE=VM_PROT_EXECUTE;
+ PAGE_PROT_WRITE =VM_PROT_WRITE;
+ PAGE_PROT_READ =VM_PROT_READ;
PAGE_PROT_RW =PAGE_PROT_READ or PAGE_PROT_WRITE;
- PAGE_PROT_SHIFT =29;
-
- PAGE_OFS_MASK =(1 shl PAGE_PROT_SHIFT)-1; //Possible addressing in 8TB
-
//PAGE_BUSY_FLAG =DWORD($10000000);
//PAGE_PATCH_FLAG =DWORD($08000000);
var
- PAGE_MAP:PDWORD=nil;
+ PAGE_MAP :PDWORD=nil;
+ PAGE_PROT :PBYTE =nil;
-procedure pmap_mark (start,__end,__off:vm_offset_t;flags:DWORD);
+procedure pmap_mark (start,__end,__off:vm_offset_t;prots:Byte);
procedure pmap_unmark (start,__end:vm_offset_t);
-procedure pmap_mark_flags(start,__end:vm_offset_t;flags:DWORD);
-function pmap_get_raw (addr:vm_offset_t):DWORD;
+function pmap_get_prot (addr:vm_offset_t):Byte;
function pmap_get_page (addr:vm_offset_t):DWORD;
function pmap_test_cross(addr:vm_offset_t;h:Integer):Boolean;
@@ -114,6 +110,7 @@ procedure pmap_pinit(pmap:p_pmap);
var
base:Pointer;
size:QWORD;
+ prot:QWORD;
i,r:Integer;
begin
@@ -139,6 +136,9 @@ begin
PAGE_MAP:=nil;
size:=PAGE_MAP_COUNT*SizeOf(DWORD);
+ prot:=size;
+ size:=size+PAGE_MAP_COUNT;
+
r:=md_mmap(PAGE_MAP,size,MD_PROT_RW);
if (r<>0) then
@@ -147,6 +147,8 @@ begin
Assert(false,'pmap_init');
end;
+ PAGE_PROT:=Pointer(PAGE_MAP)+prot;
+
//Mapping to internal memory, isolate TODO
if Length(exclude_mem)<>0 then
begin
@@ -202,14 +204,15 @@ begin
Result:=QWORD(x) shr PAGE_SHIFT;
end;
-procedure pmap_mark(start,__end,__off:vm_offset_t;flags:DWORD);
+procedure pmap_mark(start,__end,__off:vm_offset_t;prots:Byte);
begin
start:=OFF_TO_IDX(start);
__end:=OFF_TO_IDX(__end);
__off:=OFF_TO_IDX(__off);
while (start<__end) do
begin
- PAGE_MAP[start and PAGE_MAP_MASK]:=(__off and PAGE_OFS_MASK) or flags;
+ PAGE_MAP [start and PAGE_MAP_MASK]:=__off;
+ PAGE_PROT[start and PAGE_MAP_MASK]:=prots;
Inc(__off);
Inc(start);
end;
@@ -222,32 +225,18 @@ begin
__end:=OFF_TO_IDX(__end);
while (start<__end) do
begin
- PAGE_MAP[start and PAGE_MAP_MASK]:=0;
+ PAGE_MAP [start and PAGE_MAP_MASK]:=0;
+ PAGE_PROT[start and PAGE_MAP_MASK]:=0;
Inc(start);
end;
WriteBarrier;
end;
-procedure pmap_mark_flags(start,__end:vm_offset_t;flags:DWORD);
-var
- i:vm_offset_t;
-begin
- start:=OFF_TO_IDX(start);
- __end:=OFF_TO_IDX(__end);
- while (start<__end) do
- begin
- i:=start and PAGE_MAP_MASK;
- PAGE_MAP[i]:=PAGE_MAP[i] or flags;
- Inc(start);
- end;
- WriteBarrier;
-end;
-
-function pmap_get_raw(addr:vm_offset_t):DWORD;
+function pmap_get_prot(addr:vm_offset_t):Byte;
begin
addr:=OFF_TO_IDX(addr);
addr:=addr and PAGE_MAP_MASK;
- Result:=PAGE_MAP[addr];
+ Result:=PAGE_PROT[addr];
end;
function pmap_get_page(addr:vm_offset_t):DWORD;
@@ -255,7 +244,6 @@ begin
addr:=OFF_TO_IDX(addr);
addr:=addr and PAGE_MAP_MASK;
Result:=PAGE_MAP[addr];
- Result:=Result and PAGE_OFS_MASK;
end;
function pmap_test_cross(addr:vm_offset_t;h:Integer):Boolean;
@@ -269,8 +257,6 @@ begin
Result:=False;
end else
begin
- page1:=PAGE_MAP[page1] and PAGE_OFS_MASK;
- page2:=PAGE_MAP[page2] and PAGE_OFS_MASK;
Result:=(page1<>page2);
end;
end;
@@ -297,7 +283,7 @@ asm
mov PAGE_MAP(%rip),%rax
mov (%rax,%rdi,4),%edi
//filter (rdi)
- and PAGE_OFS_MASK,%rdi
+ test %rdi,%rdi
jz _exit
//combine (rdi|rsi)
shl PAGE_SHIFT,%rdi
@@ -367,7 +353,7 @@ begin
Assert(false,'pmap_enter_object');
end;
- pmap_mark(start,__end,QWORD(base),(prot and VM_RWX) shl PAGE_PROT_SHIFT);
+ pmap_mark(start,__end,QWORD(base),(prot and VM_RWX));
end;
procedure pmap_move(pmap :pmap_t;
@@ -414,7 +400,7 @@ begin
end;
end;
- pmap_mark(start,start+size,ofs_new,(new_prot and VM_RWX) shl PAGE_PROT_SHIFT);
+ pmap_mark(start,start+size,ofs_new,(new_prot and VM_RWX));
//free old
r:=md_remove(Pointer(ofs_old),size);
@@ -483,7 +469,7 @@ begin
Assert(false,'pmap_protect');
end;
- pmap_mark(start,__end,QWORD(base_new),(new_prot and VM_RWX) shl PAGE_PROT_SHIFT);
+ pmap_mark(start,__end,QWORD(base_new),(new_prot and VM_RWX));
end;
procedure pmap_madv_free(pmap :pmap_t;
diff --git a/tools/oelf2fself/DCPsha256.pas b/tools/oelf2fself/DCPsha256.pas
new file mode 100644
index 00000000..0bbb79c6
--- /dev/null
+++ b/tools/oelf2fself/DCPsha256.pas
@@ -0,0 +1,250 @@
+{******************************************************************************}
+{* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
+{******************************************************************************}
+{* A binary compatible implementation of SHA256 *******************************}
+{******************************************************************************}
+{* Copyright (c) 1999-2002 David Barton *}
+{* Permission is hereby granted, free of charge, to any person obtaining a *}
+{* copy of this software and associated documentation files (the "Software"), *}
+{* to deal in the Software without restriction, including without limitation *}
+{* the rights to use, copy, modify, merge, publish, distribute, sublicense, *}
+{* and/or sell copies of the Software, and to permit persons to whom the *}
+{* Software is furnished to do so, subject to the following conditions: *}
+{* *}
+{* The above copyright notice and this permission notice shall be included in *}
+{* all copies or substantial portions of the Software. *}
+{* *}
+{* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *}
+{* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *}
+{* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *}
+{* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *}
+{* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *}
+{* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *}
+{* DEALINGS IN THE SOFTWARE. *}
+{******************************************************************************}
+unit DCPsha256;
+
+interface
+uses
+ Classes, Sysutils;
+
+type
+ TDCP_sha256=object
+ protected
+ fInitialized:Boolean;
+ LenHi, LenLo: longword;
+ Index: DWord;
+ CurrentHash: array[0..7] of DWord;
+ HashBuffer: array[0..63] of byte;
+ procedure Compress;
+ public
+ class function GetAlgorithm: string;
+ class function GetHashSize: integer;
+ procedure Init;
+ procedure Final(var Digest);
+ procedure Burn;
+ procedure Update(const Buffer; Size: longword);
+ end;
+
+{******************************************************************************}
+{******************************************************************************}
+implementation
+{$R-}{$Q-}
+
+function SwapDWord(a: dword): dword;
+begin
+ Result:= ((a and $FF) shl 24) or ((a and $FF00) shl 8) or ((a and $FF0000) shr 8) or ((a and $FF000000) shr 24);
+end;
+
+procedure TDCP_sha256.Compress;
+var
+ a, b, c, d, e, f, g, h, t1, t2: DWord;
+ W: array[0..63] of DWord;
+ i: longword;
+begin
+ Index:= 0;
+ FillChar(W, SizeOf(W), 0);
+ a:= CurrentHash[0]; b:= CurrentHash[1]; c:= CurrentHash[2]; d:= CurrentHash[3];
+ e:= CurrentHash[4]; f:= CurrentHash[5]; g:= CurrentHash[6]; h:= CurrentHash[7];
+ Move(HashBuffer,W,Sizeof(HashBuffer));
+ for i:= 0 to 15 do
+ W[i]:= SwapDWord(W[i]);
+ for i:= 16 to 63 do
+ W[i]:= (((W[i-2] shr 17) or (W[i-2] shl 15)) xor ((W[i-2] shr 19) or (W[i-2] shl 13)) xor
+ (W[i-2] shr 10)) + W[i-7] + (((W[i-15] shr 7) or (W[i-15] shl 25)) xor
+ ((W[i-15] shr 18) or (W[i-15] shl 14)) xor (W[i-15] shr 3)) + W[i-16];
+{
+Non-optimised version
+ for i:= 0 to 63 do
+ begin
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) +
+ ((e and f) xor (not e and g)) + K[i] + W[i];
+ t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) +
+ ((a and b) xor (a and c) xor (b and c));
+ h:= g; g:= f; f:= e; e:= d + t1; d:= c; c:= b; b:= a; a:= t1 + t2;
+ end;
+}
+
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $428a2f98 + W[0]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $71374491 + W[1]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $b5c0fbcf + W[2]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $e9b5dba5 + W[3]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $3956c25b + W[4]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $59f111f1 + W[5]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $923f82a4 + W[6]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $ab1c5ed5 + W[7]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $d807aa98 + W[8]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $12835b01 + W[9]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $243185be + W[10]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $550c7dc3 + W[11]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $72be5d74 + W[12]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $80deb1fe + W[13]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $9bdc06a7 + W[14]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $c19bf174 + W[15]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $e49b69c1 + W[16]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $efbe4786 + W[17]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $0fc19dc6 + W[18]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $240ca1cc + W[19]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $2de92c6f + W[20]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4a7484aa + W[21]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5cb0a9dc + W[22]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $76f988da + W[23]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $983e5152 + W[24]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $a831c66d + W[25]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $b00327c8 + W[26]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $bf597fc7 + W[27]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $c6e00bf3 + W[28]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $d5a79147 + W[29]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $06ca6351 + W[30]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $14292967 + W[31]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $27b70a85 + W[32]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $2e1b2138 + W[33]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $4d2c6dfc + W[34]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $53380d13 + W[35]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $650a7354 + W[36]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $766a0abb + W[37]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $81c2c92e + W[38]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $92722c85 + W[39]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $a2bfe8a1 + W[40]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $a81a664b + W[41]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $c24b8b70 + W[42]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $c76c51a3 + W[43]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $d192e819 + W[44]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $d6990624 + W[45]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $f40e3585 + W[46]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $106aa070 + W[47]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $19a4c116 + W[48]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $1e376c08 + W[49]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $2748774c + W[50]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $34b0bcb5 + W[51]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $391c0cb3 + W[52]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4ed8aa4a + W[53]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5b9cca4f + W[54]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $682e6ff3 + W[55]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+ t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $748f82ee + W[56]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1;
+ t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $78a5636f + W[57]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1;
+ t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $84c87814 + W[58]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1;
+ t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $8cc70208 + W[59]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1;
+ t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $90befffa + W[60]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1;
+ t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $a4506ceb + W[61]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1;
+ t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $bef9a3f7 + W[62]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1;
+ t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $c67178f2 + W[63]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1;
+
+ CurrentHash[0]:= CurrentHash[0] + a;
+ CurrentHash[1]:= CurrentHash[1] + b;
+ CurrentHash[2]:= CurrentHash[2] + c;
+ CurrentHash[3]:= CurrentHash[3] + d;
+ CurrentHash[4]:= CurrentHash[4] + e;
+ CurrentHash[5]:= CurrentHash[5] + f;
+ CurrentHash[6]:= CurrentHash[6] + g;
+ CurrentHash[7]:= CurrentHash[7] + h;
+ FillChar(W,Sizeof(W),0);
+ FillChar(HashBuffer,Sizeof(HashBuffer),0);
+end;
+
+class function TDCP_sha256.GetAlgorithm: string;
+begin
+ Result:= 'SHA256';
+end;
+
+class function TDCP_sha256.GetHashSize: integer;
+begin
+ Result:= 256;
+end;
+
+procedure TDCP_sha256.Init;
+begin
+ Burn;
+ CurrentHash[0]:= $6a09e667;
+ CurrentHash[1]:= $bb67ae85;
+ CurrentHash[2]:= $3c6ef372;
+ CurrentHash[3]:= $a54ff53a;
+ CurrentHash[4]:= $510e527f;
+ CurrentHash[5]:= $9b05688c;
+ CurrentHash[6]:= $1f83d9ab;
+ CurrentHash[7]:= $5be0cd19;
+ fInitialized:= true;
+end;
+
+procedure TDCP_sha256.Burn;
+begin
+ LenHi:= 0; LenLo:= 0;
+ Index:= 0;
+ FillChar(HashBuffer,Sizeof(HashBuffer),0);
+ FillChar(CurrentHash,Sizeof(CurrentHash),0);
+ fInitialized:= false;
+end;
+
+procedure TDCP_sha256.Update(const Buffer; Size: longword);
+var
+ PBuf: ^byte;
+begin
+ if not fInitialized then Exit;
+
+ Inc(LenHi,Size shr 29);
+ Inc(LenLo,Size*8);
+ if LenLo< (Size*8) then
+ Inc(LenHi);
+
+ PBuf:= @Buffer;
+ while Size> 0 do
+ begin
+ if (Sizeof(HashBuffer)-Index)<= DWord(Size) then
+ begin
+ Move(PBuf^,HashBuffer[Index],Sizeof(HashBuffer)-Index);
+ Dec(Size,Sizeof(HashBuffer)-Index);
+ Inc(PBuf,Sizeof(HashBuffer)-Index);
+ Compress;
+ end
+ else
+ begin
+ Move(PBuf^,HashBuffer[Index],Size);
+ Inc(Index,Size);
+ Size:= 0;
+ end;
+ end;
+end;
+
+procedure TDCP_sha256.Final(var Digest);
+begin
+ if not fInitialized then Exit;
+
+ HashBuffer[Index]:= $80;
+ if Index>= 56 then
+ Compress;
+ PDWord(@HashBuffer[56])^:= SwapDWord(LenHi);
+ PDWord(@HashBuffer[60])^:= SwapDWord(LenLo);
+ Compress;
+ CurrentHash[0]:= SwapDWord(CurrentHash[0]);
+ CurrentHash[1]:= SwapDWord(CurrentHash[1]);
+ CurrentHash[2]:= SwapDWord(CurrentHash[2]);
+ CurrentHash[3]:= SwapDWord(CurrentHash[3]);
+ CurrentHash[4]:= SwapDWord(CurrentHash[4]);
+ CurrentHash[5]:= SwapDWord(CurrentHash[5]);
+ CurrentHash[6]:= SwapDWord(CurrentHash[6]);
+ CurrentHash[7]:= SwapDWord(CurrentHash[7]);
+ Move(CurrentHash,Digest,Sizeof(CurrentHash));
+ Burn;
+end;
+
+end.
diff --git a/tools/oelf2fself/oelf2fself.lpi b/tools/oelf2fself/oelf2fself.lpi
new file mode 100644
index 00000000..33be5e49
--- /dev/null
+++ b/tools/oelf2fself/oelf2fself.lpi
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
diff --git a/tools/oelf2fself/oelf2fself.lpr b/tools/oelf2fself/oelf2fself.lpr
new file mode 100644
index 00000000..22641476
--- /dev/null
+++ b/tools/oelf2fself/oelf2fself.lpr
@@ -0,0 +1,1166 @@
+program oelf2fself;
+
+uses
+ sysutils,
+ DCPsha256,
+ elf64 in '..\..\sys\elf64.pas',
+ ps4libdoc;
+
+const
+ PAGE_SHIFT=14;
+ PAGE_SIZE =1 shl PAGE_SHIFT; //16384
+ PAGE_MASK =PAGE_SIZE-1;
+
+ BLOCK_SIZE=$4000;
+
+ SELF_MODE_SPECIFICUSER = $1;
+ SELF_DATA_LSB = $1;
+
+ SELF_HEADER_SIZE =$20;
+ SELF_ENTRY_SIZE =$50;
+ SELF_ELF_HEADER_SIZE =$40;
+ SELF_ELF_PROGHEADER_SIZE =$38;
+ SELF_EXTENDED_HEADER_SIZE =$40;
+ SELF_META_FOOTER_SIZE =$50;
+ SELF_NPDRM_BLOCK_SIZE =$30;
+ SELF_META_BLOCK_SIZE =$50;
+ SELF_META_DATA_BLOCK_SIZE =$20;
+ SELF_SIGNATURE_SIZE =$100;
+
+type
+ Tsha256Digest=array[0..31] of Byte;
+
+ Tsignature=array[0..SELF_SIGNATURE_SIZE-1] of Byte;
+
+ AByte=array of byte;
+
+ SelfEntryInfo=record
+ data:AByte;
+ info:t_self_segment;
+ end;
+
+ a_self_segment=array of SelfEntryInfo;
+
+ p_image_params=^t_image_params;
+ t_image_params=packed record
+ image_self :p_self_header;
+ image_header:p_elf64_hdr;
+ entry_addr :Pointer;
+ elf_size :Integer;
+
+ dyn_vaddr:p_elf64_dyn;
+
+ tls_size :QWORD;
+ tls_align :QWORD;
+ tls_init_size:QWORD;
+ tls_init_addr:Pointer;
+
+ eh_frame_hdr_addr:Pointer;
+ eh_frame_hdr_size:QWORD;
+
+ proc_param_addr:pSceProcParam;
+ proc_param_size:QWORD;
+
+ module_param_addr:psceModuleParam;
+ module_param_size:QWORD;
+
+ dyn_id :Integer;
+ sce_dynlib_data_id:Integer;
+ sce_comment_id :Integer;
+ dyn_exist :Integer;
+
+ dyn_offset :QWORD;
+ dyn_filesz :QWORD;
+
+ sce_dynlib_data_addr:QWORD;
+ sce_dynlib_data_size:QWORD;
+
+ sce_comment_offset :QWORD;
+ sce_comment_filesz :QWORD;
+
+ min_addr:QWORD;
+ max_addr:QWORD;
+
+ _selfEntries:a_self_segment;
+
+ outputFself:THandle;
+ end;
+
+function maxInt64(a,b:Int64):Int64; inline;
+begin
+ if (a>b) then Result:=a else Result:=b;
+end;
+
+function minInt64(a,b:Int64):Int64; inline;
+begin
+ if (aSizeOf(DWORD)) then
+ begin
+ FileClose(F);
+ Exit(-3);
+ end;
+
+ obj_size:=FileSeek(F,0,fsFromEnd);
+
+ if (obj_size<=0) then
+ begin
+ FileClose(F);
+ Exit(-4);
+ end;
+
+ case Magic of
+ ELFMAG: //elf64
+ begin
+ elf_hdr:=AllocMem(obj_size);
+
+ FileSeek(F,0,fsFromBeginning);
+ n:=FileRead(F,elf_hdr^,obj_size);
+ FileClose(F);
+
+ if (n<>obj_size) then
+ begin
+ FreeMem(elf_hdr);
+ elf_hdr:=nil;
+ Exit(-5);
+ end;
+
+ imgp^.image_header:=elf_hdr;
+ imgp^.image_self :=nil;
+ imgp^.elf_size :=obj_size;
+ end;
+ else
+ begin
+ Exit(-5);
+ end;
+ end;
+
+end;
+
+function scan_phdr(imgp:p_image_params;phdr:p_elf64_phdr;count:Integer):Integer;
+var
+ i:Integer;
+ text_id :Integer;
+ data_id :Integer;
+ sce_relro_id:Integer;
+ vaddr:QWORD;
+ memsz:QWORD;
+begin
+ if (imgp=nil) then Exit(-1);
+ if (phdr=nil) then Exit(-1);
+ if (count=0) then Exit(-1);
+
+ imgp^.min_addr:=High(Int64);
+ imgp^.max_addr:=0;
+
+ text_id :=-1;
+ data_id :=-1;
+ sce_relro_id:=-1;
+ imgp^.dyn_id:=-1;
+
+ if (count<>0) then
+ For i:=0 to count-1 do
+ begin
+
+ case phdr[i].p_type of
+ PT_LOAD,
+ PT_SCE_RELRO:
+ begin
+ vaddr:=phdr[i].p_vaddr;
+
+ if ((phdr[i].p_align and PAGE_MASK)<>0) or
+ ((vaddr and PAGE_MASK)<>0) or
+ ((phdr[i].p_offset and PAGE_MASK)<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' is not page aligned');
+ Exit(-2);
+ end;
+
+ memsz:=phdr[i].p_memsz;
+
+ if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if (memsz > $7fffffff) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if ((phdr[i].p_offset shr $20)<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset');
+ Exit(-2);
+ end;
+
+ imgp^.min_addr:=MinInt64(imgp^.min_addr,vaddr);
+
+ vaddr:=(vaddr+memsz+$3fff) and QWORD($ffffffffffffc000);
+
+ imgp^.max_addr:=MaxInt64(imgp^.max_addr,vaddr);
+
+ if (phdr[i].p_type=PT_SCE_RELRO) then
+ begin
+ sce_relro_id:=i;
+ end else
+ if ((phdr[i].p_flags and PF_X)=0) then
+ begin
+ if (data_id=-1) then data_id:=i;
+ end else
+ begin
+ text_id:=i;
+ end;
+ end;
+
+ PT_DYNAMIC:
+ begin
+ imgp^.dyn_exist :=1;
+ imgp^.dyn_id :=i;
+ imgp^.dyn_vaddr :=Pointer(phdr[i].p_vaddr);
+ imgp^.dyn_offset:=phdr[i].p_offset;
+ imgp^.dyn_filesz:=phdr[i].p_filesz;
+
+ memsz:=phdr[i].p_memsz;
+
+ if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if (memsz > $7fffffff) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if ((phdr[i].p_offset shr $20)<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset');
+ Exit(-2);
+ end;
+ end;
+
+ PT_TLS:
+ begin
+ imgp^.tls_size :=phdr[i].p_memsz;
+ imgp^.tls_align :=phdr[i].p_align;
+ imgp^.tls_init_size:=phdr[i].p_filesz;
+ imgp^.tls_init_addr:=Pointer(phdr[i].p_vaddr);
+
+ memsz:=phdr[i].p_memsz;
+
+ if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if (memsz > $7fffffff) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if ((phdr[i].p_offset shr $20)<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset');
+ Exit(-2);
+ end;
+
+ if (phdr[i].p_align > 32) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' alignment of segment #',i,' it must be less than 32.');
+ Exit(-2);
+ end;
+ end;
+
+ PT_SCE_DYNLIBDATA:
+ begin
+ imgp^.sce_dynlib_data_id :=i;
+ imgp^.sce_dynlib_data_addr:=phdr[i].p_offset;
+ imgp^.sce_dynlib_data_size:=phdr[i].p_filesz;
+
+ if (phdr[i].p_memsz<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if (phdr[i].p_filesz > $7fffffff) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_filesz');
+ Exit(-2);
+ end;
+
+ if ((phdr[i].p_offset shr $20)<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset');
+ Exit(-2);
+ end;
+ end;
+
+ PT_SCE_PROCPARAM:
+ begin
+ imgp^.proc_param_addr:=Pointer(phdr[i].p_vaddr);
+ imgp^.proc_param_size:=phdr[i].p_filesz;
+ end;
+
+ PT_SCE_MODULE_PARAM:
+ begin
+ imgp^.module_param_addr:=Pointer(phdr[i].p_vaddr);
+ imgp^.module_param_size:=phdr[i].p_filesz;
+ end;
+
+ PT_GNU_EH_FRAME:
+ begin
+ imgp^.eh_frame_hdr_addr:=Pointer(phdr[i].p_vaddr);
+ imgp^.eh_frame_hdr_size:=phdr[i].p_memsz;
+
+ memsz:=phdr[i].p_memsz;
+
+ if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if (memsz > $7fffffff) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if ((phdr[i].p_offset shr $20)<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset');
+ Exit(-2);
+ end;
+ end;
+
+ PT_SCE_COMMENT:
+ begin
+ imgp^.sce_comment_id :=i;
+ imgp^.sce_comment_offset:=phdr[i].p_offset;
+ imgp^.sce_comment_filesz:=phdr[i].p_filesz;
+
+ if (phdr[i].p_memsz<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz');
+ Exit(-2);
+ end;
+
+ if (phdr[i].p_filesz > $7fffffff) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_filesz');
+ Exit(-2);
+ end;
+
+ if ((phdr[i].p_offset shr $20)<>0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset');
+ Exit(-2);
+ end;
+ end;
+
+ end;
+
+ end;
+
+ if (imgp^.min_addr=High(Int64)) then
+ begin
+ Exit(-2);
+ end;
+
+ if (imgp^.max_addr=0) then
+ begin
+ Exit(-2);
+ end;
+
+ if (imgp^.dyn_exist<>0) then
+ begin
+ if (imgp^.sce_dynlib_data_size=0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' sce_dynlib_data_size is zero');
+ Exit(-2);
+ end;
+
+ if (imgp^.dyn_filesz=0) then
+ begin
+ Writeln(StdErr,'scan_phdr:',' dyn_filesz is zero');
+ Exit(-2);
+ end;
+ end;
+
+ if (sce_relro_id<>-1) then
+ begin
+ vaddr:=phdr[sce_relro_id].p_vaddr;
+
+ if (vaddr=0) then
+ begin
+ Exit(-2);
+ end;
+
+ memsz:=phdr[sce_relro_id].p_memsz;
+
+ if (memsz=0) then
+ begin
+ Exit(-2);
+ end;
+
+ if (((phdr[text_id].p_vaddr+phdr[text_id].p_memsz+$1fffff) and QWORD($ffffffffffe00000))<>vaddr) and
+ (((phdr[text_id].p_vaddr+phdr[text_id].p_memsz+$003fff) and QWORD($ffffffffffffc000))<>vaddr) then
+ begin
+ Exit(-2);
+ end;
+
+ if (((vaddr+memsz+$1fffff) and QWORD($ffffffffffe00000))<>phdr[data_id].p_vaddr) and
+ (((vaddr+memsz+$003fff) and QWORD($ffffffffffffc000))<>phdr[data_id].p_vaddr) then
+ begin
+ Exit(-2);
+ end;
+ end;
+
+ Result:=0;
+end;
+
+function exec_oelf_imgact(imgp:p_image_params):Integer;
+var
+ hdr :p_elf64_hdr;
+ phdr:p_elf64_phdr;
+begin
+ Result:=0;
+
+ if (imgp=nil) then Exit(-1);
+
+ hdr:=imgp^.image_header;
+
+ hdr^.e_shoff :=0;
+ hdr^.e_shentsize:=0;
+ hdr^.e_shnum :=0;
+ hdr^.e_shstrndx :=0;
+
+ if (hdr=nil) then Exit(-1);
+
+ Case hdr^.e_type of
+ ET_SCE_EXEC ,
+ ET_SCE_REPLAY_EXEC,
+ ET_SCE_DYNEXEC :
+ else
+ begin
+ Writeln(StdErr,'exec_oelf_imgact:',' unspported e_type:0x',HexStr(hdr^.e_type,4));
+ Exit(-2);
+ end;
+ end;
+
+ if (hdr^.e_machine<>EM_X86_64) then
+ begin
+ Writeln(StdErr,'exec_oelf_imgact:',' unspported e_machine:',hdr^.e_machine);
+ Exit(-2);
+ end;
+
+ phdr:=get_elf_phdr(hdr);
+
+ Result:=scan_phdr(imgp,phdr,hdr^.e_phnum);
+ if (Result<>0) then
+ begin
+ Writeln(StdErr,'exec_oelf_imgact:','found illegal segment header');
+ Exit;
+ end;
+
+ if (imgp^.dyn_exist=0) and (hdr^.e_type=ET_SCE_DYNEXEC) then
+ begin
+ Writeln(StdErr,'exec_oelf_imgact:','illegal ELF file image');
+ Exit(-2);
+ end;
+
+end;
+
+procedure sha256(P:Pointer;S:longword;F:PByte);
+Var
+ D:TDCP_sha256;
+begin
+ D.Init;
+ D.Update(P^,S);
+ D.Final(F^);
+end;
+
+function setProperty(prop,bit,mask,val:QWORD):QWORD; inline;
+begin
+ Result:=prop or ((val and mask) shl bit);
+end;
+
+procedure append(var A:a_self_segment;S:SelfEntryInfo);
+var
+ i:Integer;
+begin
+ i:=Length(A);
+ SetLength(A,i+1);
+ A[i]:=S;
+end;
+
+function ilog2(i:QWORD):QWORD; inline;
+begin
+ Result:=BsfQWORD(i or 1);
+end;
+
+function make(size:sizeint):AByte; inline;
+begin
+ Result:=nil;
+ SetLength(Result,size);
+end;
+
+function createSelfEntries(imgp:p_image_params;
+ prog:p_elf64_phdr;
+ prog_size:Integer):Integer;
+var
+ i,entryIndex:Integer;
+ metaEntryProperties:QWORD;
+ dataEntryProperties:QWORD;
+ seg:SelfEntryInfo;
+begin
+ entryIndex:=0;
+
+ for i:=0 to prog_size-1 do
+ begin
+
+ if (prog^.p_type <> PT_LOAD) and
+ (prog^.p_type <> PT_SCE_RELRO) and
+ (prog^.p_type <> PT_SCE_DYNLIBDATA) then
+ begin
+ Inc(prog);
+ continue;
+ end;
+
+ metaEntryProperties:=0;
+
+ metaEntryProperties:=metaEntryProperties or SELF_PROPS_SIGNED;
+ metaEntryProperties:=metaEntryProperties or SELF_PROPS_HAS_DIGESTS;
+ metaEntryProperties:=setProperty(metaEntryProperties, SELF_PROPS_SEGMENT_INDEX_OFFSET, SELF_PROPS_SEGMENT_INDEX_MASK, entryIndex+1);
+
+ seg:=Default(SelfEntryInfo);
+ seg.info.flags:=metaEntryProperties;
+
+ append(imgp^._selfEntries,seg);
+
+ dataEntryProperties:=0;
+
+ dataEntryProperties:=dataEntryProperties or SELF_PROPS_SIGNED;
+ dataEntryProperties:=dataEntryProperties or SELF_PROPS_BLOCKED;
+ dataEntryProperties:=setProperty(dataEntryProperties, SELF_PROPS_BLOCK_SIZE_OFFSET , SELF_PROPS_BLOCK_SIZE_MASK , ilog2(BLOCK_SIZE)-12);
+ dataEntryProperties:=setProperty(dataEntryProperties, SELF_PROPS_SEGMENT_INDEX_OFFSET, SELF_PROPS_SEGMENT_INDEX_MASK, i);
+
+ seg:=Default(SelfEntryInfo);
+ seg.info.flags:=dataEntryProperties;
+
+ append(imgp^._selfEntries,seg);
+
+ entryIndex += 2;
+ Inc(prog);
+ end;
+
+ Result:=length(imgp^._selfEntries) * SELF_META_DATA_BLOCK_SIZE;
+end;
+
+function writeNullPadding(imgp:p_image_params;
+ size,_align:Integer):Integer;
+var
+ buf:Pointer;
+ w:sizeint;
+begin
+ size:=(-size) and (_align-1);
+ if (size=0) then Exit(0);
+
+ buf:=AllocMem(size);
+
+ w:=FileWrite(imgp^.outputFself,buf^,size);
+ if (w<>size) then
+ begin
+ Writeln(StdErr,'writeNullBytes:',' FileWrite:',w);
+ end;
+
+ FreeMem(buf);
+ Result:=size;
+end;
+
+function writeSelfHeader(imgp:p_image_params;
+ version:byte;
+ mode:byte;
+ endian:byte;
+ attr:byte;
+ headerSize:word;
+ fileSize:QWORD;
+ flags:word):Integer;
+var
+ selfHeader:t_self_header;
+ w:sizeint;
+begin
+ selfHeader.Magic :=SELF_MAGIC;
+ selfHeader.Version :=version;
+ selfHeader.Mode :=mode;
+ selfHeader.Endian :=endian;
+ selfHeader.Attr :=attr;
+ selfHeader.Content_Type:=1;
+ selfHeader.Program_Type:=1;
+ selfHeader.Padding :=0;
+ selfHeader.Header_Size :=headerSize;
+ selfHeader.Meta_size :=(length(imgp^._selfEntries) * SELF_ENTRY_SIZE) + SELF_META_FOOTER_SIZE + SELF_SIGNATURE_SIZE;
+ selfHeader.File_size :=fileSize;
+ selfHeader.Num_Segments:=length(imgp^._selfEntries);
+ selfHeader.Flags :=flags;
+ selfHeader.reserved :=0;
+
+ w:=FileWrite(imgp^.outputFself,selfHeader,SizeOf(selfHeader));
+ if (w<>SizeOf(selfHeader)) then
+ begin
+ Writeln(StdErr,'writeSelfHeader:',' FileWrite:',w);
+ end;
+
+ Result:=SizeOf(selfHeader);
+end;
+
+function writeSelfEntries(imgp:p_image_params):Integer;
+var
+ i:Integer;
+ w:sizeint;
+begin
+ Result:=0;
+
+ for i:=0 to high(imgp^._selfEntries) do
+ begin
+
+ w:=FileWrite(imgp^.outputFself,imgp^._selfEntries[i].info,SizeOf(t_self_segment));
+ if (w<>SizeOf(t_self_segment)) then
+ begin
+ Writeln(StdErr,'writeSelfEntries:',' FileWrite:',w);
+ end;
+
+ Result:=Result+SizeOf(t_self_segment);
+ end;
+
+end;
+
+function writeELFHeaders(imgp:p_image_params):Integer;
+var
+ hdr:elf64_hdr;
+ prog:p_elf64_phdr;
+ prog_size:Integer;
+ w,s:sizeint;
+begin
+ Result:=0;
+
+ prog:=get_elf_phdr(imgp^.image_header);
+ prog_size:=imgp^.image_header^.e_phnum;
+
+ hdr:=Default(elf64_hdr);
+ hdr:=imgp^.image_header^;
+
+ w:=FileWrite(imgp^.outputFself,hdr,SizeOf(elf64_hdr));
+ if (w<>SizeOf(elf64_hdr)) then
+ begin
+ Writeln(StdErr,'writeELFHeaders:',' FileWrite:',w);
+ end;
+
+ Result:=SizeOf(elf64_hdr);
+
+ s:=Sizeof(elf64_phdr)*prog_size;
+
+ w:=FileWrite(imgp^.outputFself,prog^,s);
+ if (w<>s) then
+ begin
+ Writeln(StdErr,'writeELFHeaders:',' FileWrite:',w);
+ end;
+
+ Result:=Result+s;
+end;
+
+function writeExtendedInfo(imgp:p_image_params;
+ pType:RawByteString;
+ paid:uint64;
+ appVersion:uint64;
+ fwVersion:uint64;
+ var digest:Tsha256Digest):Integer;
+var
+ extendedHeader:t_self_authinfo;
+ programType:Integer;
+ w:Integer;
+begin
+ programType := SELF_PT_FAKE;
+
+ case lowercase(Trim(pType)) of
+ 'npdrm_exec' :programType:=SELF_PT_NPDRM_EXEC;
+ 'npdrm_dynlib' :programType:=SELF_PT_NPDRM_DYNLIB;
+ 'system_exec' :programType:=SELF_PT_SYSTEM_EXEC;
+ 'system_dynlib':programType:=SELF_PT_SYSTEM_DYNLIB;
+ 'host_kernel' :programType:=SELF_PT_HOST_KERNEL;
+ 'secure_module':programType:=SELF_PT_SECURE_MODULE;
+ 'secure_kernel':programType:=SELF_PT_SECURE_KERNEL;
+ else;
+ end;
+
+ extendedHeader.AuthorityID :=paid;
+ extendedHeader.Program_Type :=programType;
+ extendedHeader.Program_Version:=appVersion;
+ extendedHeader.System_Version :=fwVersion;
+ extendedHeader.Digest_SHA_256 :=digest;
+
+ w:=FileWrite(imgp^.outputFself,extendedHeader,sizeof(t_self_authinfo));
+ if (w<>sizeof(t_self_authinfo)) then
+ begin
+ Writeln(StdErr,'writeExtendedInfo:',' FileWrite:',w);
+ end;
+
+ Result:=sizeof(t_self_authinfo);
+end;
+
+function writeNpdrmControlBlock(imgp:p_image_params):Integer;
+var
+ controlBlock:t_self_npdrm_control_block;
+ w:Integer;
+begin
+ controlBlock:=Default(t_self_npdrm_control_block);
+ controlBlock.pType:=SELF_CONTROL_BLOCK_TYPE_NPDRM;
+
+ w:=FileWrite(imgp^.outputFself,controlBlock,sizeof(t_self_npdrm_control_block));
+ if (w<>sizeof(t_self_npdrm_control_block)) then
+ begin
+ Writeln(StdErr,'writeNpdrmControlBlock:',' FileWrite:',w);
+ end;
+
+ Result:=sizeof(t_self_npdrm_control_block);
+end;
+
+function writeMetaBlocks(imgp:p_image_params):Integer;
+var
+ buf:Pointer;
+ w,size:sizeint;
+begin
+ size:=SELF_META_BLOCK_SIZE*length(imgp^._selfEntries);
+ buf:=AllocMem(size);
+
+ w:=FileWrite(imgp^.outputFself,buf^,size);
+ if (w<>size) then
+ begin
+ Writeln(StdErr,'writeMetaBlocks:',' FileWrite:',w);
+ end;
+
+ FreeMem(buf);
+ Result:=size;
+end;
+
+function writeMetaFooter(imgp:p_image_params;val:DWORD):Integer;
+var
+ buf:Pointer;
+ w,size:sizeint;
+begin
+ size:=SELF_META_FOOTER_SIZE;
+ buf:=AllocMem(size);
+
+ PDWORD(buf+$30)^:=val;
+
+ w:=FileWrite(imgp^.outputFself,buf^,size);
+ if (w<>size) then
+ begin
+ Writeln(StdErr,'writeMetaFooter:',' FileWrite:',w);
+ end;
+
+ FreeMem(buf);
+ Result:=size;
+end;
+
+function writeSignature(imgp:p_image_params;var signature:Tsignature):Integer;
+var
+ w:sizeint;
+begin
+
+ w:=FileWrite(imgp^.outputFself,signature,sizeof(Tsignature));
+ if (w<>sizeof(Tsignature)) then
+ begin
+ Writeln(StdErr,'writeSignature:',' FileWrite:',w);
+ end;
+
+ Result:=sizeof(Tsignature);
+end;
+
+function writeSegments(imgp:p_image_params):Integer;
+var
+ i:Integer;
+ w,s:sizeint;
+begin
+ Result:=0;
+
+ for i:=0 to high(imgp^._selfEntries) do
+ begin
+
+ //Writeln(imgp^._selfEntries[i].info.offset,':',Length(imgp^._selfEntries[i].data));
+
+ s:=imgp^._selfEntries[i].info.offset;
+ w:=FileSeek(imgp^.outputFself,s,fsFromBeginning);
+ if (w<>s) then
+ begin
+ Writeln(StdErr,'writeSegments:',' FileSeek:',w);
+ end;
+
+ s:=Length(imgp^._selfEntries[i].data);
+
+ w:=FileWrite(imgp^.outputFself,imgp^._selfEntries[i].data[0],s);
+ if (w<>s) then
+ begin
+ Writeln(StdErr,'writeSegments:',' FileWrite:',w);
+ end;
+
+ Result:=Result+s;
+ end;
+
+end;
+
+function CreateFSELF(imgp:p_image_params;
+ outputPath:RawByteString;
+ paid:int64;
+ pType:RawByteString;
+ appVersion:int64;
+ fwVersion:int64;
+ authInfo:RawByteString):Integer;
+
+var
+ sha256Digest:Tsha256Digest;
+ signature:Tsignature;
+ headerSize:QWORD;
+ offset:QWORD;
+ fileSize:QWORD;
+ finalFileSize:QWORD;
+ prog:p_elf64_phdr;
+ prog_size:Integer;
+ i,entryIndex:Integer;
+ numBlocks:Integer;
+ signedBlockCount:Integer;
+ flags:Integer;
+ metaData:AByte;
+ segmentData:AByte;
+ base:Pointer;
+begin
+
+ imgp^.outputFself:=FileCreate(outputPath);
+
+ if (imgp^.outputFself=THandle(-1)) then
+ begin
+ Writeln(StdErr,'CreateFSELF:',' FileCreate error');
+ Exit;
+ end;
+
+ sha256Digest:=Default(Tsha256Digest);
+ sha256(imgp^.image_header,imgp^.elf_size,@sha256Digest);
+
+ signature:=Default(Tsignature);
+
+ {
+ if authInfo != "" {
+ signature = createSignature(authInfo, paid)
+ }
+ }
+
+ prog:=get_elf_phdr(imgp^.image_header);
+ prog_size:=imgp^.image_header^.e_phnum;
+
+ headerSize := SELF_HEADER_SIZE;
+ headerSize += createSelfEntries(imgp,prog,prog_size);
+ headerSize += SELF_ELF_HEADER_SIZE;
+ headerSize += prog_size * SELF_ELF_PROGHEADER_SIZE;
+
+ headerSize := Align(headerSize, $10);
+
+ headerSize += SELF_EXTENDED_HEADER_SIZE;
+ headerSize += SELF_NPDRM_BLOCK_SIZE;
+
+ entryIndex := 0;
+ offset := headerSize + (length(imgp^._selfEntries)*SELF_ENTRY_SIZE)+SELF_META_FOOTER_SIZE+SELF_SIGNATURE_SIZE;
+
+ for i:=0 to prog_size-1 do
+ begin
+
+ if (prog^.p_type <> PT_LOAD) and
+ (prog^.p_type <> PT_SCE_RELRO) and
+ (prog^.p_type <> PT_SCE_DYNLIBDATA) then
+ begin
+ Inc(prog);
+ continue;
+ end;
+
+ numBlocks := align(prog^.p_filesz, BLOCK_SIZE) div BLOCK_SIZE;
+
+ metaData:=make(SELF_META_DATA_BLOCK_SIZE*numBlocks);
+
+ imgp^._selfEntries[entryIndex].Data := metaData;
+ imgp^._selfEntries[entryIndex].info.offset := offset;
+ imgp^._selfEntries[entryIndex].info.filesz := length(metaData);
+ imgp^._selfEntries[entryIndex].info.memsz := length(metaData);
+
+ offset += imgp^._selfEntries[entryIndex].info.filesz;
+ offset := align(offset, $10);
+
+ segmentData := make(prog^.p_filesz);
+
+ base:=Pointer(imgp^.image_header)+prog^.p_offset;
+ Move(base^,segmentData[0],length(segmentData));
+
+ imgp^._selfEntries[entryIndex+1].Data := segmentData;
+ imgp^._selfEntries[entryIndex+1].info.offset := offset;
+ imgp^._selfEntries[entryIndex+1].info.filesz := prog^.p_filesz;
+ imgp^._selfEntries[entryIndex+1].info.memsz := prog^.p_filesz;
+
+ offset += imgp^._selfEntries[entryIndex+1].info.filesz;
+ offset := align(offset, $10);
+
+ entryIndex += 2;
+ Inc(prog);
+ end;
+
+ fileSize := offset;
+
+ signedBlockCount := $2;
+ flags := $2 or ((signedBlockCount and $7) shl 4);
+
+ finalFileSize := 0;
+
+ finalFileSize += writeSelfHeader(imgp,
+ 0,
+ SELF_MODE_SPECIFICUSER,
+ SELF_DATA_LSB,
+ $12,
+ headerSize,
+ fileSize,
+ flags
+ );
+
+ finalFileSize += writeNullPadding(imgp, finalFileSize, $10);
+ finalFileSize += writeSelfEntries(imgp);
+ finalFileSize += writeELFHeaders(imgp);
+ finalFileSize += writeNullPadding(imgp, finalFileSize, $10);
+ finalFileSize += writeExtendedInfo(imgp, pType, paid, appVersion, fwVersion, sha256Digest);
+ finalFileSize += writeNpdrmControlBlock(imgp);
+ finalFileSize += writeMetaBlocks(imgp);
+ finalFileSize += writeMetaFooter(imgp, $10000);
+ finalFileSize += writeSignature(imgp, signature);
+ finalFileSize += writeSegments(imgp);
+
+ FileClose(imgp^.outputFself);
+
+ Result:=0;
+end;
+
+function get_sdk_version_str(version:QWORD):RawByteString;
+begin
+ Result:=HexStr((version shr 24),2)+'.'+HexStr(((version shr 12) and $fff),3)+'.'+HexStr((version and $fff),3);
+end;
+
+function HexToDword(S:RawByteString;_def:DWORD):DWORD;
+begin
+ Result:=_def;
+
+ if (copy(S,1,2)='0x') then
+ begin
+ Delete(S,1,2);
+ S:='$'+S;
+ end;
+
+ TryStrToUInt(S,Result);
+end;
+
+function HexToQword(S:RawByteString;_def:QWORD):QWORD;
+begin
+ Result:=_def;
+
+ if (copy(S,1,2)='0x') then
+ begin
+ Delete(S,1,2);
+ S:='$'+S;
+ end;
+
+ TryStrToUInt64(S,Result);
+end;
+
+var
+ InputFileName :RawByteString=''; //input Orbis OELF filepath
+ OutputFileName:RawByteString=''; //output Orbis FSELF filepath
+ sdkver :DWORD =$1000051; //SDK version integer
+ ptype :RawByteString=''; //program type
+ authInfo :RawByteString=''; //authentication info
+ paid :QWORD =$3800000000000011; //program authentication ID
+ appVer :QWORD =0; //application version
+ fwVer :QWORD =0; //firmware version
+
+procedure parse_param;
+var
+ i:Integer;
+ S:RawByteString;
+ n:Integer;
+begin
+ n:=-1;
+ For i:=1 to ParamCount do
+ begin
+ S:=Trim(ParamStr(i));
+
+ case LowerCase(S) of
+ '-i':n:=0;
+ '-o':n:=1;
+ '-sdkver':n:=2;
+ '-ptype':n:=3;
+ '-authinfo':n:=4;
+ '-paid':n:=5;
+ '-appver':n:=6;
+ '-fwver':n:=7;
+ else
+ if (n<>-1) then
+ begin
+ Case n of
+ 0:InputFileName :=S;
+ 1:OutputFileName:=S;
+ 2:sdkver :=HexToDword(S,sdkver);
+ 3:ptype :=LowerCase(S);
+ 4:authInfo :=S;
+ 5:paid :=HexToQword(S,paid);
+ 6:appVer :=HexToQword(S,appVer);
+ 7:fwVer :=HexToQword(S,fwVer);
+ end;
+ n:=-1;
+ end else
+ begin
+ InputFileName:=S;
+ end;
+ end;
+
+ end;
+end;
+
+var
+ r:Integer;
+ img:t_image_params;
+
+begin
+ parse_param;
+
+ if (ParamCount<=1) or (InputFileName='') then
+ begin
+
+ Writeln('Usage: oelf2fself