首页
社区
课程
招聘
[原创]微软的驱动里的一个疑惑
发表于: 2015-6-16 21:04 4022

[原创]微软的驱动里的一个疑惑

2015-6-16 21:04
4022
.text:000115EC ; NTSTATUS __stdcall TpmGetCommandResultLoop(int a1, int *OutputSize, int OutputBuffer, int a4)
.text:000115EC _TpmGetCommandResultLoop@16 proc near   ; CODE XREF: TpmGetCommandResult(x,x,x,x)+36p
.text:000115EC
.text:000115EC BurstValue      = dword ptr -0Ch
.text:000115EC i               = dword ptr -8
.text:000115EC Bitset          = dword ptr -1
.text:000115EC a1              = dword ptr  8
.text:000115EC OutputSize      = dword ptr  0Ch
.text:000115EC OutputBuffer    = dword ptr  10h
.text:000115EC duration_status = dword ptr  14h
.text:000115EC
.text:000115EC                 mov     edi, edi
.text:000115EE                 push    ebp
.text:000115EF                 mov     ebp, esp
.text:000115F1                 sub     esp, 0Ch
.text:000115F4                 and     [ebp+BurstValue], 0
.text:000115F8                 and     [ebp+i], 0
.text:000115FC                 push    ebx
.text:000115FD                 push    esi
.text:000115FE                 mov     esi, ds:__imp__DbgPrintEx
.text:00011604                 push    edi
.text:00011605                 push    0Ah
.text:00011607                 pop     ebx
.text:00011608                 push    offset aTpmgetcomman_1 ; "TpmGetCommandResultLoop: Enter\n"
.text:0001160D                 push    3               ; Level
.text:0001160F                 push    72h             ; ComponentId
.text:00011611                 mov     byte ptr [ebp+Bitset], 0
.text:00011615                 call    esi ; __imp__DbgPrintEx
.text:00011617                 push    [ebp+duration_status]
.text:0001161A                 push    offset aTpmgetcomman_5 ; "TpmGetCommandResultLoop: waiting %ums.\n"...
.text:0001161F                 push    3               ; Level
.text:00011621                 push    72h             ; ComponentId
.text:00011623                 call    esi ; __imp__DbgPrintEx
.text:00011625                 mov     edi, [ebp+a1]
.text:00011628                 add     esp, 1Ch
.text:0001162B                 lea     eax, [ebp+Bitset]
.text:0001162E                 push    eax             ; int
.text:0001162F                 push    [ebp+duration_status] ; int
.text:00011632                 push    90h             ; int
.text:00011637                 push    18h             ; Value
.text:00011639                 push    edi             ; int
.text:0001163A                 call    _TpmWaitForBitSet@20 ; TpmWaitForBitSet(x,x,x,x,x)
.text:0001163F                 mov     [ebp+duration_status], eax
.text:00011642                 test    eax, eax
.text:00011644                 jge     short loc_11659
.text:00011646                 push    offset aTpmgetcommandr ; "TpmGetCommandResultLoop: Timeout while "...
.text:0001164B                 push    1               ; Level
.text:0001164D                 push    72h             ; ComponentId
.text:0001164F                 call    esi ; __imp__DbgPrintEx
.text:00011651                 add     esp, 0Ch
.text:00011654                 jmp     loc_118AF
.text:00011659 ; ---------------------------------------------------------------------------
.text:00011659
.text:00011659 loc_11659:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+58j
.text:00011659                 push    offset aTpmgetcomman_2 ; "TpmGetCommandResultLoop: reading respon"...
.text:0001165E                 push    3               ; Level
.text:00011660                 push    72h             ; ComponentId
.text:00011662                 call    esi ; __imp__DbgPrintEx
.text:00011664                 add     esp, 0Ch
.text:00011667
.text:00011667 loc_11667:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+16Dj
.text:00011667                 lea     eax, [ebp+Bitset]
.text:0001166A                 push    eax             ; int
.text:0001166B                 push    dword ptr [edi+2Ch] ; int
.text:0001166E                 push    90h             ; int
.text:00011673                 push    18h             ; Value
.text:00011675                 push    edi             ; int
.text:00011676                 call    _TpmWaitForBitSet@20 ; TpmWaitForBitSet(x,x,x,x,x)
.text:0001167B                 mov     [ebp+duration_status], eax
.text:0001167E                 test    eax, eax
.text:00011680                 jl      loc_117A3
.text:00011686                 push    dword ptr [edi+30h]
.text:00011689                 lea     eax, [ebp+BurstValue]
.text:0001168C                 push    eax
.text:0001168D                 push    edi
.text:0001168E                 call    _TpmGetNextBurstValue@12 ; TpmGetNextBurstValue(x,x,x)
.text:00011693                 mov     [ebp+duration_status], eax
.text:00011696                 test    eax, eax
.text:00011698                 jl      loc_117BB
.text:0001169E                 movzx   ecx, word ptr [ebp+BurstValue]
.text:000116A2                 mov     eax, ebx
.text:000116A4                 sub     eax, [ebp+i]
.text:000116A7                 dec     eax
.text:000116A8                 cmp     ecx, eax
.text:000116AA                 jnb     short loc_116AE
.text:000116AC                 mov     eax, ecx        
.text:000116AE
.text:000116AE loc_116AE:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+BEj
.text:000116AE                 push    eax
.text:000116AF                 push    offset aTpmgetcomma_14 ; "TpmGetCommandResultLoop: reading burst "...
.text:000116B4                 push    3               ; Level
.text:000116B6                 push    72h             ; ComponentId
.text:000116B8                 call    esi ; __imp__DbgPrintEx
.text:000116BA                 add     esp, 10h
.text:000116BD                 jmp     loc_11749
.text:000116C2 ; ---------------------------------------------------------------------------
.text:000116C2
.text:000116C2 loc_116C2:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+162j
.text:000116C2                 lea     eax, [ebx-1]
.text:000116C5                 cmp     [ebp+i], eax
.text:000116C8                 jnb     loc_11754
.text:000116CE                 push    24h             ; Offset
.text:000116D0                 push    edi             ; int
.text:000116D1                 call    _TpmINB@8       ; TpmINB(x,x)
.text:000116D6                 mov     edx, [ebp+i]
.text:000116D9                 mov     ecx, [ebp+OutputBuffer]
.text:000116DC                 mov     [edx+ecx], al
.text:000116DF                 cmp     edx, 5
.text:000116E2                 jnz     short loc_1172A
.text:000116E4                 movzx   ebx, byte ptr [ecx+2]
.text:000116E8                 movzx   eax, byte ptr [ecx+3]
.text:000116EC                 shl     ebx, 8
.text:000116EF                 or      ebx, eax
.text:000116F1                 movzx   eax, byte ptr [ecx+4]
.text:000116F5                 shl     ebx, 8
.text:000116F8                 or      ebx, eax
.text:000116FA                 movzx   eax, byte ptr [ecx+5]
.text:000116FE                 shl     ebx, 8
.text:00011701                 or      ebx, eax        
.text:00011703                 mov     eax, [ebp+OutputSize]
.text:00011706                 mov     eax, [eax]
.text:00011708                 cmp     ebx, eax
.text:0001170A                 jbe     short loc_11721
.text:0001170C                 push    ebx
.text:0001170D                 push    eax
.text:0001170E                 push    offset aTpmgetcomma_16 ; "TpmGetCommandResultLoop: output buffer "...
.text:00011713                 push    1               ; Level
.text:00011715                 push    72h             ; ComponentId
.text:00011717                 call    esi ; __imp__DbgPrintEx
.text:00011719                 mov     eax, [ebp+OutputSize]
.text:0001171C                 mov     ebx, [eax]
.text:0001171E                 add     esp, 14h
.text:00011721
.text:00011721 loc_11721:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+11Ej
.text:00011721                 cmp     ebx, 0Ah
.text:00011724                 jb      loc_117C3
.text:0001172A
.text:0001172A loc_1172A:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+F6j
.text:0001172A                 mov     eax, [edi+1Ch]
.text:0001172D                 cmp     eax, 2
.text:00011730                 jz      loc_118AF
.text:00011736                 cmp     eax, 3
.text:00011739                 jz      loc_118AF
.text:0001173F                 add     [ebp+BurstValue], 0FFFFh
.text:00011746                 inc     [ebp+i]
.text:00011749
.text:00011749 loc_11749:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+D1j
.text:00011749                 cmp     word ptr [ebp+BurstValue], 0
.text:0001174E                 ja      loc_116C2
.text:00011754
.text:00011754 loc_11754:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+DCj
.text:00011754                 cmp     word ptr [ebp+BurstValue], 0
.text:00011759                 jz      loc_11667
.text:0001175F                 push    offset aTpmgetcomma_11 ; "TpmGetCommandResultLoop: checking for u"...
.text:00011764                 push    3               ; Level
.text:00011766                 push    72h             ; ComponentId
.text:00011768                 call    esi ; __imp__DbgPrintEx
.text:0001176A                 add     esp, 0Ch
.text:0001176D                 lea     eax, [ebp+Bitset]
.text:00011770                 push    eax             ; int
.text:00011771                 push    dword ptr [edi+2Ch] ; int
.text:00011774                 push    90h             ; int
.text:00011779                 push    18h             ; Value
.text:0001177B                 push    edi             ; int
.text:0001177C                 call    _TpmWaitForBitSet@20 ; TpmWaitForBitSet(x,x,x,x,x)
.text:00011781                 test    eax, eax
.text:00011783                 jge     short loc_117FB
.text:00011785                 push    offset aTpmgetcomman_0 ; "TpmGetCommandResultLoop: TPM has fewer "...
.text:0001178A                 push    1               ; Level
.text:0001178C                 push    72h             ; ComponentId
.text:0001178E                 call    esi ; __imp__DbgPrintEx
.text:00011790                 add     esp, 0Ch
.text:00011793                 push    4
.text:00011795
.text:00011795 loc_11795:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+2B2j
.text:00011795                 mov     ecx, [edi]
.text:00011797                 mov     eax, 0C0000186h
.text:0001179C                 push    eax
.text:0001179D                 mov     [ebp+duration_status], eax
.text:000117A0                 push    ecx
.text:000117A1                 jmp     short loc_117DF
.text:000117A3 ; ---------------------------------------------------------------------------
.text:000117A3
.text:000117A3 loc_117A3:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+94j
.text:000117A3                 movzx   eax, byte ptr [ebp+Bitset]
.text:000117A7                 push    eax
.text:000117A8                 push    offset aTpmgetcomman_9 ; "TpmGetCommandResultLoop: Timeout while "...
.text:000117AD
.text:000117AD loc_117AD:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+1D5j
.text:000117AD                                         ; TpmGetCommandResultLoop(x,x,x,x)+291j
.text:000117AD                 push    1               ; Level
.text:000117AF                 push    72h             ; ComponentId
.text:000117B1                 call    esi ; __imp__DbgPrintEx
.text:000117B3                 add     esp, 10h
.text:000117B6                 jmp     loc_118AF
.text:000117BB ; ---------------------------------------------------------------------------
.text:000117BB
.text:000117BB loc_117BB:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+ACj
.text:000117BB                 push    eax
.text:000117BC                 push    offset aTpmgetcomman_7 ; "TpmGetCommandResultLoop: TpmGetNextBurs"...
.text:000117C1                 jmp     short loc_117AD
.text:000117C3 ; ---------------------------------------------------------------------------
.text:000117C3
.text:000117C3 loc_117C3:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+138j
.text:000117C3                 push    ebx
.text:000117C4                 push    offset aTpmgetcomma_12 ; "TpmGetCommandResultLoop: response size "...
.text:000117C9                 push    1               ; Level
.text:000117CB                 push    72h             ; ComponentId
.text:000117CD                 call    esi ; __imp__DbgPrintEx
.text:000117CF                 mov     eax, [edi]
.text:000117D1                 add     esp, 10h
.text:000117D4                 push    3               ; Site
.text:000117D6                 push    ebx             ; Info
.text:000117D7                 mov     [ebp+duration_status], 0C0000186h
.text:000117DE                 push    eax             ; _DWORD
.text:000117DF
.text:000117DF loc_117DF:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+1B5j
.text:000117DF                 push    _WdfDriverGlobals ; _DWORD
.text:000117E5                 call    WdfDeviceWdmGetDeviceObject
.text:000117EB                 push    eax             ; Device
.text:000117EC                 push    0C006000Fh      ; SymbolNameValue
.text:000117F1                 call    _TpmLogEvent@16 ; TpmLogEvent(x,x,x,x)
.text:000117F6                 jmp     loc_118AF
.text:000117FB ; ---------------------------------------------------------------------------
.text:000117FB
.text:000117FB loc_117FB:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+197j
.text:000117FB                 mov     eax, [ebp+i]
.text:000117FE                 mov     ecx, [ebp+OutputSize]
.text:00011801                 cmp     eax, [ecx]
.text:00011803                 jnb     short loc_1181B
.text:00011805                 push    24h            
.text:00011807                 push    edi            
.text:00011808                 call    _TpmINB@8       ; TpmINB(x,x)
.text:0001180D                 mov     edx, [ebp+i]
.text:00011810                 mov     ecx, [ebp+OutputBuffer]
.text:00011813                 inc     [ebp+i]
.text:00011816                 mov     [edx+ecx], al
.text:00011819                 jmp     short loc_1181E
.text:0001181B ; ---------------------------------------------------------------------------
.text:0001181B
.text:0001181B loc_1181B:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+217j
.text:0001181B                 mov     ecx, [ebp+OutputBuffer]
.text:0001181E
.text:0001181E loc_1181E:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+22Dj
.text:0001181E                 movzx   eax, byte ptr [ecx+2]
.text:00011822                 movzx   edx, byte ptr [ecx+3]
.text:00011826                 shl     eax, 8
.text:00011829                 or      eax, edx
.text:0001182B                 movzx   edx, byte ptr [ecx+4]
.text:0001182F                 movzx   ecx, byte ptr [ecx+5]
.text:00011833                 shl     eax, 8
.text:00011836                 or      eax, edx
.text:00011838                 shl     eax, 8
.text:0001183B                 or      eax, ecx
.text:0001183D                 cmp     ebx, eax        
.text:0001183F                 jz      short loc_1184A
.text:00011841                 mov     [ebp+duration_status], 80000005h ; STATUS_BUFFER_OVERFLOW
.text:00011848                 jmp     short loc_118AF
.text:0001184A ; ---------------------------------------------------------------------------
.text:0001184A
.text:0001184A loc_1184A:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+253j
.text:0001184A                 push    offset aTpmgetcomma_10 ; "TpmGetCommandResultLoop: checking for o"...
.text:0001184F                 push    3               ; Level
.text:00011851                 push    72h             ; ComponentId
.text:00011853                 call    esi ; __imp__DbgPrintEx
.text:00011855                 add     esp, 0Ch
.text:00011858                 lea     eax, [ebp+Bitset]
.text:0001185B                 push    eax             ; int
.text:0001185C                 push    dword ptr [edi+2Ch] ; int
.text:0001185F                 push    80h             ; int
.text:00011864                 push    18h             ; Value
.text:00011866                 push    edi             ; int
.text:00011867                 call    _TpmWaitForBitSet@20 ; TpmWaitForBitSet(x,x,x,x,x)
.text:0001186C                 mov     [ebp+duration_status], eax
.text:0001186F                 test    eax, eax
.text:00011871                 jge     short loc_11882
.text:00011873                 movzx   eax, byte ptr [ebp+Bitset]
.text:00011877                 push    eax
.text:00011878                 push    offset aTpmgetcomman_8 ; "TpmGetCommandResultLoop: failed to get "...
.text:0001187D                 jmp     loc_117AD
.text:00011882 ; ---------------------------------------------------------------------------
.text:00011882
.text:00011882 loc_11882:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+285j
.text:00011882                 cmp     byte ptr [edi+42h], 0
.text:00011886                 jnz     short loc_118A3
.text:00011888                 test    byte ptr [ebp+Bitset], 10h
.text:0001188C                 jz      short loc_118A3
.text:0001188E                 push    offset aTpmgetcomman_4 ; "TpmGetCommandResultLoop: TPM has more b"...
.text:00011893                 push    1               ; Level
.text:00011895                 push    72h             ; ComponentId
.text:00011897                 call    esi ; __imp__DbgPrintEx
.text:00011899                 add     esp, 0Ch
.text:0001189C                 push    5
.text:0001189E                 jmp     loc_11795
.text:000118A3 ; ---------------------------------------------------------------------------
.text:000118A3
.text:000118A3 loc_118A3:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+29Aj
.text:000118A3                                         ; TpmGetCommandResultLoop(x,x,x,x)+2A0j
.text:000118A3                 mov     eax, [ebp+i]
.text:000118A6                 mov     ecx, [ebp+OutputSize]
.text:000118A9                 and     [ebp+duration_status], 0
.text:000118AD                 mov     [ecx], eax
.text:000118AF
.text:000118AF loc_118AF:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+68j
.text:000118AF                                         ; TpmGetCommandResultLoop(x,x,x,x)+144j ...
.text:000118AF                 mov     edi, [edi+1Ch]
.text:000118B2                 cmp     edi, 2
.text:000118B5                 jz      short loc_118BC
.text:000118B7                 cmp     edi, 3
.text:000118BA                 jnz     short loc_118C3
.text:000118BC
.text:000118BC loc_118BC:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+2C9j
.text:000118BC                 mov     [ebp+duration_status], 0C0000120h
.text:000118C3
.text:000118C3 loc_118C3:                              ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+2CEj
.text:000118C3                 push    [ebp+duration_status]
.text:000118C6                 push    offset aTpmgetcomma_13 ; "TpmGetCommandResultLoop: Exiting with s"...
.text:000118CB                 push    3               ; Level
.text:000118CD                 push    72h             ; ComponentId
.text:000118CF                 call    esi ; __imp__DbgPrintEx
.text:000118D1                 mov     eax, [ebp+duration_status]
.text:000118D4                 add     esp, 10h
.text:000118D7                 pop     edi
.text:000118D8                 pop     esi
.text:000118D9                 pop     ebx
.text:000118DA                 leave
.text:000118DB                 retn    10h
.text:000118DB _TpmGetCommandResultLoop@16 endp

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 315
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
问题出在这句
.text:000116C2                 lea     eax, [ebx-1]
.text:000116C5                 cmp     [ebp+i], eax
.text:000116C8                 jnb     loc_11754

ebx = 0xA  为恒定值
本来这个函数是用于读取 TpmCmd 的返回值,最小10个字节长度
可它却把返回值限定在了 10 个字节,意味着每个 Tpm Ordinal 的返回都是10个字节,
而它却利用大于10个字节后的数据

直接引发的效果是: Bitlocker 加密的密钥是 64 个0,这下蛋疼了

有谁给我个 win8 系统中的微软 tpm.sys 文件?我想看看
2015-6-16 21:09
0
雪    币: 315
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
.text:0001159E ; __stdcall TpmGetNextBurstValue(x, x, x)
.text:0001159E _TpmGetNextBurstValue@12 proc near      ; CODE XREF: TpmGetCommandResultLoop(x,x,x,x)+A2p
.text:0001159E                                         ; TpmWriteCommandAndStart(x,x,x)+36p
.text:0001159E
.text:0001159E arg_0           = dword ptr  8
.text:0001159E arg_4           = dword ptr  0Ch
.text:0001159E arg_8           = dword ptr  10h
.text:0001159E
.text:0001159E                 mov     edi, edi
.text:000115A0                 push    ebp
.text:000115A1                 mov     ebp, esp
.text:000115A3                 push    esi
.text:000115A4                 mov     esi, [ebp+arg_4]
.text:000115A7                 push    edi
.text:000115A8                 xor     edi, edi
.text:000115AA                 xor     eax, eax
.text:000115AC                 mov     [esi], ax
.text:000115AF                 jmp     short loc_115C5
.text:000115B1 ; ---------------------------------------------------------------------------
.text:000115B1
.text:000115B1 loc_115B1:                              ; CODE XREF: TpmGetNextBurstValue(x,x,x)+37j
.text:000115B1                 push    [ebp+arg_0]
.text:000115B4                 call    _TpmPollDelay@4 ; TpmPollDelay(x)
.text:000115B9                 mov     edi, eax
.text:000115BB                 test    edi, edi
.text:000115BD                 jl      short loc_115DE
.text:000115BF                 sub     [ebp+arg_8], 10
.text:000115C3                 js      short loc_115D9
.text:000115C5
.text:000115C5 loc_115C5:                              ; CODE XREF: TpmGetNextBurstValue(x,x,x)+11j
.text:000115C5                 push    19h             ; Value
.text:000115C7                 push    [ebp+arg_0]     ; int
.text:000115CA                 call    _TpmINW@8       ; TpmINW(x,x)
.text:000115CF                 mov     [esi], ax
.text:000115D2                 test    ax, ax
.text:000115D5                 jbe     short loc_115B1
.text:000115D7                 jmp     short loc_115DE
.text:000115D9 ; ---------------------------------------------------------------------------
.text:000115D9
.text:000115D9 loc_115D9:                              ; CODE XREF: TpmGetNextBurstValue(x,x,x)+25j
.text:000115D9                 mov     edi, 0C0000186h
.text:000115DE
.text:000115DE loc_115DE:                              ; CODE XREF: TpmGetNextBurstValue(x,x,x)+1Fj
.text:000115DE                                         ; TpmGetNextBurstValue(x,x,x)+39j
.text:000115DE                 mov     eax, edi
.text:000115E0                 pop     edi
.text:000115E1                 pop     esi
.text:000115E2                 pop     ebp
.text:000115E3                 retn    0Ch
.text:000115E3 _TpmGetNextBurstValue@12 endp
2015-6-16 22:50
0
雪    币: 315
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
TpmGetNextBurstValue 函数代码也存在问题
应该是这样才是标准的

TpmINW(a0,0x19) | (TpmINW(a0,0x20) << 8)
2015-6-16 22:51
0
雪    币: 315
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
第三个代码错误位于 TPM_CallDSMMethod 函数中
在计算 _DSM 方法返回的数据长度和复制返回数据应该使用宏 ACPI_METHOD_NEXT_ARGUMENT

而代码却使用了
for(i = 0 ; i < OutputBuffer->Count; i++)
{
    NumberOfBytes += OutputBuffer->Argument[i].DataLength;
}

应该写为

for(i = 0 ; i < OutputBuffer->Count; i++)
{
    NumberOfBytes += Argument->DataLength;
    Argument  = ACPI_METHOD_NEXT_ARGUMENT(Argument);
}
2015-6-16 23:32
0
游客
登录 | 注册 方可回帖
返回
//