From b9f9afc99b8a79defdbab677e94c02faca39705f Mon Sep 17 00:00:00 2001 From: headkaze Date: Sat, 11 Dec 2021 13:35:40 -0500 Subject: [PATCH] MacSerial, Codecs.plist, pic.ids update --- Hackintool.xcodeproj/project.pbxproj | 14 +- .../UserInterfaceState.xcuserstate | Bin 127596 -> 129091 bytes MacSerial/UserPseudoRandom.c | 71 + MacSerial/UserPseudoRandom.h | 14 + MacSerial/macserial.c | 1274 ++++++++--------- MacSerial/macserial.h | 7 +- MacSerial/modelinfo_autogen.h | 31 +- Resources/Audio/Codecs.plist | 8 + Resources/PCI/pci.ids | 86 +- 9 files changed, 820 insertions(+), 685 deletions(-) create mode 100644 MacSerial/UserPseudoRandom.c create mode 100644 MacSerial/UserPseudoRandom.h diff --git a/Hackintool.xcodeproj/project.pbxproj b/Hackintool.xcodeproj/project.pbxproj index 551af990..bd13ecbb 100644 --- a/Hackintool.xcodeproj/project.pbxproj +++ b/Hackintool.xcodeproj/project.pbxproj @@ -65,6 +65,7 @@ E2D20D4D223184DF00BAC721 /* Clover in Resources */ = {isa = PBXBuildFile; fileRef = E2D20D4C223184DF00BAC721 /* Clover */; }; E2DDD8AA2306DE640017F6D7 /* macserial.c in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD8A62306DE640017F6D7 /* macserial.c */; }; E2DDD8AE2307E3800017F6D7 /* efidevp.c in Sources */ = {isa = PBXBuildFile; fileRef = E2DDD8AC2307E37F0017F6D7 /* efidevp.c */; }; + E2E97BE9276522AB00A7BEBE /* UserPseudoRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = E2E97BE7276522AB00A7BEBE /* UserPseudoRandom.c */; }; E2ED92F8221349FE00279FEA /* AudioDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = E2ED92F7221349FE00279FEA /* AudioDevice.m */; }; E2F6B2C522E3FE2B00BEF274 /* IORegTools.m in Sources */ = {isa = PBXBuildFile; fileRef = E2F6B2C422E3FE2B00BEF274 /* IORegTools.m */; }; E2FB8637210EAB1000D6F0E4 /* FBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = E2FB8635210EAB1000D6F0E4 /* FBUtilities.m */; }; @@ -186,6 +187,8 @@ E2E7D7F2220811AC0062D06D /* uk */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; E2E7D7F62208124A0062D06D /* de */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; E2E9476F2204A9F5005348C0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + E2E97BE7276522AB00A7BEBE /* UserPseudoRandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = UserPseudoRandom.c; sourceTree = ""; }; + E2E97BE8276522AB00A7BEBE /* UserPseudoRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserPseudoRandom.h; sourceTree = ""; }; E2EA734A22845CDB0095E56C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = "zh-Hans"; path = "zh-Hans.lproj/Credits.rtf"; sourceTree = ""; }; E2ED92F6221349F000279FEA /* AudioDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioDevice.h; sourceTree = ""; }; E2ED92F7221349FE00279FEA /* AudioDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioDevice.m; sourceTree = ""; }; @@ -351,6 +354,8 @@ E2DDD8A52306DE640017F6D7 /* MacSerial */ = { isa = PBXGroup; children = ( + E2E97BE7276522AB00A7BEBE /* UserPseudoRandom.c */, + E2E97BE8276522AB00A7BEBE /* UserPseudoRandom.h */, E2DDD8A62306DE640017F6D7 /* macserial.c */, E2DDD8A72306DE640017F6D7 /* macserial.h */, E2DDD8A82306DE640017F6D7 /* modelinfo.h */, @@ -559,6 +564,7 @@ E2489DEE211AE5AD00A48C84 /* NSTabViewImage.m in Sources */, E2520BA5226CE3B00077A0FC /* PCIMonitor.m in Sources */, E277608E21EBD90D00EA6E44 /* FixEDID.m in Sources */, + E2E97BE9276522AB00A7BEBE /* UserPseudoRandom.c in Sources */, E2DDD8AA2306DE640017F6D7 /* macserial.c in Sources */, E200EE7A21FBD4600082D799 /* NVRAMXmlParser.m in Sources */, E22AB5392278FC4500A46C8D /* OpenCore.m in Sources */, @@ -715,7 +721,7 @@ CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0376; + CURRENT_PROJECT_VERSION = 0377; DEVELOPMENT_TEAM = 5LGHPJM9ZR; ENABLE_HARDENED_RUNTIME = YES; ENABLE_STRICT_OBJC_MSGSEND = NO; @@ -730,7 +736,7 @@ INFOPLIST_FILE = "Hackintool/Hackintool-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 3.7.6; + MARKETING_VERSION = 3.7.7; PRODUCT_BUNDLE_IDENTIFIER = com.Headsoft.Hackintool; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -751,7 +757,7 @@ CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 0376; + CURRENT_PROJECT_VERSION = 0377; DEVELOPMENT_TEAM = 5LGHPJM9ZR; ENABLE_HARDENED_RUNTIME = YES; ENABLE_STRICT_OBJC_MSGSEND = NO; @@ -766,7 +772,7 @@ INFOPLIST_FILE = "Hackintool/Hackintool-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 3.7.6; + MARKETING_VERSION = 3.7.7; PRODUCT_BUNDLE_IDENTIFIER = com.Headsoft.Hackintool; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Hackintool.xcodeproj/project.xcworkspace/xcuserdata/headsoft.xcuserdatad/UserInterfaceState.xcuserstate b/Hackintool.xcodeproj/project.xcworkspace/xcuserdata/headsoft.xcuserdatad/UserInterfaceState.xcuserstate index b4af644a8cdedfecb451fe477ce86b8df12563c6..2e0cec8ddd1ec6ab082804ead567652ed73dae61 100644 GIT binary patch literal 129091 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 literal 127596 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

7sS*BLt#x=Q!E_Xz_^LOYKL~TwJ#Xjwv71% z5gZ(O%x2h%88uTw8<@dUZ+cFWYr}1A9Z}u22Is&*W{bx=e8iZd;*zw|@l}&1PpO_+ zQ@dc%+@YT*N}bh)B@)I4uS%_P|L7k&OfaKE(lp~Et8rKb6i z5OP{Rsik2B%c3%b*NZo|L)iF{*`IXnb&kg43{f#EMD5H%V?}vOsAfY1J;vN>mTEb6 z0qodsGmnsG|dBF_LtPL%U^e_1p-$jQCGGZ2Ogs>lz!~FKS_V??2Jq zeZYk1kf@=%ydr9hnpm!Gq^_mR9Im!-qI*QY8UM9*LwhLki-9u;I}V&WZF-&BM6Hn5 z0`+T15oR;gyR8+P*F9|pq&!pM2%eZVd+Cgt>75-7u$L3V;f4)cX3d#_##6q7J!)N< zOqHtOiMjJ&K6e#t_xu_CT*ciB>tc=Fy>JHpT)YIvGl@P;DzUnk;_-g2a}sCdT-;D@ zB$vk(bJg55ZZ=oLwQ-%?q1@5jN!m2S1JO}9pOtgc7*u{oMHm%*5Aw_jmD z*?y({D#fIENc6(0k?14Qf0_LnzRG@`{d&F%(N8hJqMu@r#B}yWcL+0eX?wOwj52?E zQ>C)OX84{{VmH-vY+zl)pWIp7%p3>YnLa^ME55^iC(PPi_Pd#h=)lj+Uw_r%%SRWL zrg$y(d+qmuH7t{E`@PJGHrBQ^HEakpbOds9%X0Gr6Q`>^1OmccoGF?Tk7?K+wPP%$ zTad&>CS8qwN|u+Ls>YdHBsWv)s(aTk(7It`5QImoO(m$-!Aj?=15~L#?6u5 zh5k`ZI2D`Jv9qbUP4(P*%lcO}ap=)MQSM}sICN^#MfHXQ{&u-5n+a_YcA zs&i$wSZ#KP)8+PfJ#dE8hL7!^u$Zo6)&?StuOU z!Db7R9M#M4_4M+?!1Ldmew~mg_;ju z)z-dd{f0v}(Gf=;d))CSpK|J%XPteX>aAk1or6XUuohGrFpz`)tAFJd7Y62{9%Us< z;4oHV6u1JtOBOavnv%(*mT?xwa=5BRWfC-eJ{JyRVbMI*v0AWB(UbFCTR3Bn&#kU%W%0qLIV{W(!bZvNvE$Og=T=v$UYO#7CI7@+U&SBZuih}Uw4gFKucUHfW>HCgWoBMMMNVdA zaY=4w!Nk0(;+&jGIR%r-7jMijC}8S?&rPWE`~_(E_W{sEOL5_P>xo+%TvmXjxqobw*uE0+R}ht19zz z3o=U!aw{??<>r-V=HwQXWabuBRu$#tRpd=9DqWngEIFHA2uE@|I@8y#gXz;WLv4*@ zVZ{tC_@VMry`!%ZI(y%s-mE+v^+tVB4^(*L#-frE&BWyuBY)}9m{jx;jB>5UunSo;>MHoPDQ-%E3LO+stJ zLM@5YGS;3E9fc%DCM8j#bOV2uM6n{GbIxTW)x_ZHobgL@))y~tV8SiQZ!FH~GlFU1 z4&jdA&f&V0G0W}TQ`}DOQ|?EMPDbhqbmMi?bTgC@N)5&+^K|od3o%kzqB}^pOxL7a zu3L$*%7wZv-Tk^pbua2Z(S52<(WmN-dY3*Iqmn{>v3`Gjg?@&9zJ9%aqy8xUiTX43 zm*}_ZFVk<=_vo+EU!%WCe~bP$j8g8>-=n`z|ET_5{g3*e^}pzUOBtGyn^Kfgl`;6DiN7JfHGn%F8Lg4;VPWG{7>zHo!69fC1A6 z%pI_9zi+Xmb*;H3dy4)~5w;RSvOZ{*FqmCxp<@U!_Eel9}yp_ZUNqmUJN7%K;nOkH)KTxx>ZQYE9waw@;Sm1|UivP)isTiK%(%g>bmgbJ; zP(+DFtG89RM%tAjeB!qFlge$2=OOxB8Cur4Vg(Cso2Q3Xw}m%M4mY%~OkCB<5YK@H zWYt-Vq*$(Ff@2Ev2q!wq9TkpBN0noe1NELp;&c*ckT{dXStQOTan9wAYR7?&sg7xm z>5dr=T(2Rqmc+#*wvc!@i6@eHC9AtpoAHU48S#M0;kM3p^#?crh@`61AXzBV)aH(? z_^nyhkw|9`} zqJ)SSDTDEN!FmZs5nx<8h4GtqTYB|@U8*oF{#-waqc`u21*(I4x-TZd-L!$4ui8xi zO(Sc%G3}*n$98|Gyj^jvdCh=h9vsoG1uunE!fWQb+#*eEMLW86g zm`7@8#{|$MOy7bF%+c%3bBs)IovC#EUKTjPH9M|V#b#cV_`VuN!!K;~R22@lg^?=a z^x#@mD;wf~;q0e)LcO12V;Y>M0jII=V;=m*3=fN(hcRV=`K}HGpp{-d!p3Cm$4L1G zHKxN#8@n*46LV?It7ndFJY%IXmFHr^I^?U)V>!;X7hy*J8zn5_xIhVuz@bez1$l*V z7D`!{skP)KjxNlnIxcl=CUG^1t=*1p#}*RXNIZ;**}0}O6y7ikf%4Uu<_Jd;{__$H zesN`1LkB)vwdA%t5d7NexWdunxYB{ZS38MoNDPx0!6q2TwT|l?*JBaC*g+y@GuE;k zY)m9<&aibwO=DYosA6SX8)o5QE7%NQRYPP$ZCiCKtTBB2*{m?iU}uq1E;h_$^A{%N zuNv5A%si?y*(w{#8#)?SGTPUM)^{jR*Dl9jFFEdT-08T>akt|hZiwSv$9>#$T-foT zg;y_J%@V0-h=l4`B(_N@Wu5Y~QWO#oC2^e;#Y7nRx#v!Psryc)t zJhKqvf`~FpN8*NgnAERsMI&Rz+VPxYhcXoqi}b4g{uW$*p4*7gh5EO8>x+(;b`gXs z1mxW9c$r1xn9jtd6#sFT>j~+#wzY=Tq+fHq&W^Cz_32)X(Cv7G@1L}CedWL=lg*oz6)wyK^h&s<4Xy%W@!HMb zJATBhtK$a}kL_~&L?Vs=f@8kh$5?y+>iEs^J7zdAR%C`|7MmTy)Sapq%HW*D6G%LM zrcv+d9l1zLAGHuOnX8p@!%txg>(WRgn{1!e7J&k_wJu4XsgGPH3^G`q zz8#_@53Fr(=vcWBsu5a01*=@TQj?~J4crcdHwN~XyfSyqCa#nMe0uZ96T5Ng@m^mgj%%2+X9 z^_{c**zTdjyN6|@YffqUgy<~gd-sTu=@Z%w%J=jMr`)G}=^Bl4j2XBk)0~x*`_e?r zH>;t&T^S*`xh!rxHi&F2<#%ej?Y1almRa3^yYaoe~a?rO|#+>iN<$GF$HPq=Tn zpSWLif-#k|}iEOklb z0mmh;DDh`fmP&V99LuhLUQK;|ZsIf$#G4O-LF~_rp#KJ=%QPZUO8s- zSMAy-t7?z*8dqsuKU77TN7m}-ai+m5b$XpXr{5WHVhRW|$7hjvHi_quc{lX6v_gJ9C_vgE^nX3!>L1DHVFRgjxlL4GZL|j}&3v z$5~9`MbT?sa+W#AI>&KCoa3GQb7AKMpxjyEMEuU6#rm{$A4?P5g152~l8cW>=3w$1 z)<2|P$CIlOV@=!+|EHRn#F@*rG!wtE-ue>uv7N+=NxU2ajr->+ZJ=gMDp^(QLyeux z{8qKDZ4S4!vSku#PHMF#W4WbsinH2zpc7-)OG)e|aVv@2Fe~Mp;hc#&;^1TFoVrBb zbCpt&xS9D0$rRUmR4S)y8nxlT;=GDkFF15`&rNorO@bGX|% zpIL%E-lG+0;Xu)e5z-b)!DrWk+LerHfn4q999CX5tWrGf;xhH(WwA2*#x*hW1|lj! z0$A@8NVNL?=EMI`|ECszrL$R`gy<#OL|uA!m)*{TSykAi#a`XNxOjOezqp`jS$^R% zOm!tY%*AKato;r4Ahk+ zteKX>oKZL;P6Pq2?{dPA!opcNB12f(Y$Z!%VkG(Qqn*d7tH+=oN#g}p{oFhjrqhx= z!HKt4XvxAB-;89n-%fL$t|o%+bAr+@X}_H9JQq{BPS~{Dx}4{ccsr9z5Y{L>OIrho zg>|77h?rEZhh=6q1LRc|r0xcn67hl6V)1cawMz ziT9FtABp#q_(1fUdP7l68=1{tj!7$JSyCv>hS>2?j+SLsd{qbRrxt|Rs|Q(Bz1~pp zSMpNTm@QIDj~k5sOU1}hZx|cDYuB(s-+J`AV_MsazgV<#IDlXggi!ofYJ|?Q6+=)o z8J-*wFK+*pn%&vlxN1tMrM=!Tq5n*>CbE^Qv2~VvY^?MNYgF$?quCA4n;6ZYcn^1R z!_Z%XWo~6K&HDeCPBBj?Hrm&oyWM#gM#0WIoZ!==BtF*7HXSf`Lfv*{jVCcJ)UYbl zr1tiR_b-?e|0U)jObWNHj(0Cw@(((nr)4`Y9PMB>jRu_c&H7y&ibIK8u_qnWL>!nm{ptLE4; zK6P3EV<)xq4~3NE{Iurf+5*WQ$8saAN+|4DCG>#gOd zEUCj(UGlgKVO-eDSm719sL@}m_E4xnDWv8zj@YA|nlXi|3J|d*Q%v5|Ld!d9+vX%4 zp6dM4`88wlS0ujD<@|<3WtV^v4tKmolwL$Njz8$PcRPP{Vx;*RiSNYMR62ig{=wO{ zIDd8i=KP(+*GYVX#5cFNIBu9rPvTq5lYASddkKcVHHqKEy)oAqS0?jrJ|*!p#rsOn z#0)GtFLkaiQjX3Q+eA86&Izr+Kt8;InQ@~oE9M8e@&;ed9{+*{*ztI>+os)7%vZ5H zzG5*?v8(qackCY9hl7{k9$_atMNsV0o}8fiSl=o>R+2~kD)+Rj$~DO~*)@e5;;QDJ zbRFoLDqN>q=9-SlsAaAhu9;leHPba4&QAo<40VXq(z&`-o#O{xLrT|xAY{@-W8+Fh z2C`MQBiXXjB9~wp{uTr#Y0qY zj6~?xkLZX0i`_wLiI=#RE<$-3AJ~AS+f~nPOunGezrnQ}E~aaltI^fuLdg6-B>qC; zuO$Aq)wRO4(oonN&(kN8Wb&9z>J7$sg)Qwv+C^6xW%edjSaKb3l&qte$}#D z<6?`iuhMqmdFcg^};|qw+Wws3+F+q93sJxx!nrZ&c#0UbI(dOA~9gSy*#ECxkG0qyycvvNa%K;2(88iN*7-$6SxQo*>CVl9MFY z7S~gQmkbn1axs8lluGd{}xZZTV<$Bxoj_Y05d#?9gAGkhredPMs^>5cFu1`tw zkd#SM8A(+n)soas66kOqNjH;pKS^(r^dFLWk~2uoBY6(Vog|+}@|7gtLGn+O$`e*V zBChx8IGmGyU!T>vjiOAJpGZNy~TLE@efjgrzU( z?VZaoQxw}}fqfvEjhXE&oe}jTqU@*BHjHZ1@Txj$9bnchtcHtpMzoP2oB2o|&Gv*s zmW)tkp{C}hnc?OY@jsL=YE4GDN5cb%J9$ZJ*Xa8GbgBq@iae3ID8?HD_<+{|fW z8RapzDrwQNAzi!YK$Ssw(=2nE`eD#al|erm*?nRLO63D*Z{yLNW z{v=f}%^j=Az7mVx`^di0-IS1hIZ5OC$o^m^`&I51_iB>HlXL({6B4qo6CY->-=FkY zsgo@GmHkUzyShOY_r%?a`&U)m1u=0CiD^e;CflLS=7@(WQJsLgSuZJk7$`&3sw}6p zEGHNH3;N3FDEHBj(Xo)x@$M7cCz4c6(rhN9Ns5eWNSZ~`oZkFA*?mevMl(p7+($-d zF&UlhKF577NmEEVkR%*vtJU?W)Yq7dswoBRN6gkRW8R#J(-*96!Q?u|&j~YksY=qR zyCo@R(pgH=cOy0T6{?w=8IxKy>q`F4=JxD9B}{BNa9^R?teNP>`mtGm&r&VzonfD5 za}~ROaNp{_4PEFMA=8b(-&ZgzBrPUsE^9Xo$*{{qYU|x@_qgv(wA&(*=Jjc}hgrKl z;(pZq7)kR8PuL5OPv%(PzAyNzCXg1n~qJX zs~Zro3-YS!%45A8vN$BZ*DJVqY&sf8V#Ay2^38T#A%J32#q#_3TG9jf=>&>;+$T5)cMJOK~r z@gkC4&x!r3o<$!8^`v`-a$!$~>u1jh+Z~=!ByAvR9kZ)z6uXL(*`Q+Ud+DcVj3-mo zPY?R;wIqe(`bko!;x>BnA!HAFfk<2}J;kc3b?mBY@p+?|(`UP1(K#F@p?2B!#CGpIx9Zq`0mAe+i_qN46uijpj_E3}BKu7G_K(ThQzo+)?;0RnP zjjgLa>tPE$t)4bdyJw9j?1^|fJe{7ko^>Q0P0}$W9ZS-2BppxE2_&K4K8d80Njjy+ zvq80mo=pR%cyMHphnOuqHOUs9PS{8;ovqkH96Gqq7XIVMsd?D@$ULW!bed)hak9`> zIa9ho&cqu}m?6ZmRd`Dhj(^b_`~uHK%obiq(ivTzi%B|jZ*5_hhrLtPgX7dl!l`+O zcMtgmws61`{n})m>1&tY|yGfEzms03&9z2aWCW= zN_l`%9#k|BlhFG#@1NH^=7o6Rgz;#){R?xaN6fFY`jYsU%(7 z<%Ji*j(bD&_D{VKuffZ_5WdE1g4&UEJ#=W$nb4t>`}^upOwGMcuj++(RWIbmJw1aF z1?xo1Ybw=^y)_7kgvuhyXCIyPrn5+c7aoUqgm)y<$=hR*hFcVsypN=NcU4L67;ntu zU~#IuNxF4cmGr{l*y1hl7J8v1w~=%QNq5Fo(wlC1fvF@8sl#@Zcy|~NQ}x>&ddt=B z@UGn`rFXKTl+ryhH|4+Hd7ivK+&ftvtlfinY9^-E%P~8}e3DR@c_n>iI@|Swx5irw zna;NFWHNnNv2#z7^nfDNhuI$bU3?60op({f&OJdAcHhKi=9AKuTo#rvFh zhZj_ShotvNdOx9k_sMKZ8#%!}OV++U$M3vvsk-;U?sV^SRre6|P13!Oy*LQ3$NO*Z zC*DuJpLsv`e&PMn`<3@=?>8iUOwzwe`h=uUN&1YW&q?}%q%TQAoagHv?{_iX`$;{S z*83~dy>F6q@4NWPw9-%eRPTSFdOjSG+~pfc(zh|y^X&)K8|aoU80dzJ&tA@P4Es!S z@qJdG9jfQEk@S6+&q2};d#QRpkI%0-8a|)mX#5B@l7565>AU-?QB3uG!+awY)$`P2r$a<16P2aoU^Ra0Q z-vPb}K1^HuM$#W7b8*e{WvMFkyP`t9mU`@2_k7cp2W8!Ebk8?O(LFgO=1}|>XRIWh zv5!S0uvg>lFv`HTgnu z6DIFRve-wEtC%2Le5-w}BugZxk~}CO$VKv@FkwhqkA-wyi>qg1`Hgn!j5=KMtyLoH z^1$6i)_ogQnGW8aOrxqyhs0!B^|vGIy-Jses{5j2KHhg0Y^Co6--*7Hd?))( z@tx{B&3C%*4Bwd~n@Bd3Y$4f7vW;Xr$qtg8B)dp<_xR3MZKdygxyg4SKiYROY^AIm zldKNRWFLFYoSeq2r<}geSpF}J<(14>UPZE3GnUt~QQ4Dx6$7O_&(?P-pK(9McZ-j` zWYc#m$^I_i?IZ{G)>z){V=vkCv6pPhLFT6ndJ}$1%Fh1$6ytzXHG)0rQ(v;_Q(m$u z4`lV;0_FX5n4md%pKchLr)&$0W?cbCwKd7Dll*DvDim=hl?(Zl*0Z%SkJxZ?LrZ-##%Lqd?_&b&k1+wPTy5gqjV?kx_4$MCU z0`?pHMn6nWA<4xgmnH=K$KY*Dz(q8`1_3WgK9Nfs68l}M;Vs#n;r07fnV0QG=Ki6o z%*XxromtX>VaY>e|4>!-<6?^8&-AnRC-}4c+5Q}Vu0PM8?=SEd`iuOi{Q)FTAbBFm z;a=ol>tE;k z+27$m#E-6i9ve)`OG(Cf7M|EVl2PG~-WFk#|FDEbfK+PxScIdPML61jjQ?1Y=aM|1 zRx5TawQu`8bk~CwZ-68}KL8`<&jk;d}oN3EOZq$?N*qhF`f`FZ2KA|K0ybfD7mX zdXm?Zdzt4`d#iqNKz}zX70p;AJ=Eg{%2nPTzs+crw zNfuVMM>=9&S|C+*J2t9r$9&}+!{$cqS8NGqCTNqA?h^GxX{@bY-n=5B-C~h0V7FjW z8)r#$VMi@;)_!vaTI{gAE9*plTtts|#=zzFPcv;n|MW z;qgsNZ0DqE1{2GA8Tr*~d!;9RT!Fwr{?EB^pwabnAQV_0K;Lu))SV5!l*wzkhvdsi z-rh^w1I>Yh6WYFw7c#h0h@e#EA}Q;buUp>7jIFRS%U*WvvTvZiZtarB5)*A&&?!vK|L2K=P0R-Y7n%0 zdaJN@^&~a%t-Dj((^aBz>`>zAq1Mi<_07uyBg%0~)<~@xzL7p;YI+~(aXv=Z;^aHETYgl> z0T1kM91!?b&F-PyG+Izy%OXD#YqVK^tpjvw&KyYBtfc$y0xI`IHUI!p+#m9NWCgw$ZWO=h|zPVrM;K z{UFX76prgCBf2Q8Obk^{4&WqNq&XoS4n=2esw&?0|==|Yk}CHb@1sB4INf*-3BTlN{Lt7~gpJqa6J*;%1O)iVRC zD{I@>>0(n`u~t)+sdl{9bhbv?&VHQ8j>c=n0?)`a@jNr`Rtl;b*RO?NW-zNE8k`ej* zkmQe{ru?Ve5dO2^T>cCGOOoFr-3^#;-?%X|H<$S}nfbYS%89u7#kn}7H@6h$dc>Ys zs6O$I@`M{t6c!ZVfxIH+Bwx5iyFRc)ec-+L1G%{+IH_050&k(&C5Hy}fe(_(l>9(H zS%lOlK1zN9#n7_o=ZR+ZiGRlnRg$xtYO6!8;ObzjN~)zBain~HRv~l#vI&h!?GUqjB zh8rsC=9R9=EZvYa!J*9j(#+Pi@Tj%J zO4JiucQr=4I*~9+{hRDQ9Zc}V;7MFKc#7-i;Az3rgJ+QZE2Zk0xA-&bUs4B9s*X}q zdi5{Cvw~+Q`jmdOFS;Hzq@?3YA@zAS!Uk>y8_<-dcU1V5!z zYfP3Vg~dKf^-!v}H;X?Hevy!+i&D*fSo|H6<@doKfe>plxSh?iKc0Xn!i*TABre<}@p%1~5EMb8th_oM|o` zj@781BBv@+(neHD4N~g3K26Q`hNbz^{JZQ8OC3q6X{@dL-5ZuREG;9^)*~o2eb=^5 z8-un^%S_8k%cj(!lsb%3GvaOiSN4Xbm8nfSd^b(n@7}PqinJMsI;T~pRi#Zzo18W! ztvc<%w5e&+(xy}DC`uhosj$VFl$u4UC|?ex=2B`NrRMjf%~Ye#X*KHJu(bJzI;R%I zLeB8xQi~FM!&1xkMV(ciWkvqMb&6>rM4i)?Qz~{Tt5k2s@M@2H!_wN*!iYGht)bN7 zuCxfHmh5H3Ic;6qAuM!UleU2^mP#!}=y7N}A(vRw~Cifiz$YkPDOn2LQ8ydB9>| zDaTpf1l|X}27cx^>i}RNfHO6$Ccpw9Evp;w0YRVyzx0O{J0j_q;) z&)Oaa9t9o;o&=r-o&lZ%o(En8J_J4nJ^?-hz68Djz6X8+egS^tIQwv*0$2_70B>-d zV=yoo2m`3A;~d~T-~!+x;1Xan&<&uD4wTJ-Iy&&Y<0{}m0A+Nbj5xQNbD)e4l+l4Q zI#5O&EzLPlMw}VVIbH!?15j4SSHQ2p?`l&z_4v0Km;g)#YJoZc?ciJqbOP%D$jG@7 zxDJ3kosg&VegNfgqOL9;5CIt&2p~PzbYLbh8>j(}1I`A{1gWCq_=Dp-Iv@oo0jhv00NUJx za(PfL56b01nx3@)>gYioJx2g10H*@y0pODdd3YWGo&k0MF90tCuK=$BKXROx1CW;& za_~Y9*gnB|Gk{V6d3%wc7x{T12QOsood+xcLICpho&=l%oCcf$KsMgX0kpOEHUP5r zz6wA_-v4l%&j27(UjRr0h5?Y55AyOA0m#=k7T6y^TlmTWw6AXlFbkLitN@yURX_{S z3bX^80My@iI&da{HuHgxK5)=?1#l$*9q~aXzQ=)Qfj5A+fp>uqfRBKGbDW+kK0A%HdocxfJe<834SOOdjpw0Yk0CdOS0igZ-keMGc z^P`;p%|JH*UifbZ?gZ`v?g8!to(7%)o&(+lAX7hh=Z8M~KL$Plz6E{&egYuxzz_g+ z2%ruD3t$5r0OTGR0iaHSOaS!>pgw`=KplWG2kL=kKohVWhyW;aU_G!A*aRF790!~T zoD7@_K<@*Pd0;yLxd$M3#B9019RTVRKz#yF0;od(vJXJ^f%gH_BY=7YP>;Z8z!$(* z92W#XgJ_SS2*|)dU@(BX1yQ#k>J~)%1nt03AOk?%f~Z^YG~i<3QlJaif^Gomq(K&G zkOlleF3klT1)L6?34k|g=K{ZTTsrbfM_%d3D;;^IqyFhf0!IVK0>=a3OZpE0WS$P0 zr~k@vLstTwz&c<90C^345kOssqOL;%4pN#8)8-d$^I{?%#;~wBq0Cmei-7-+OjMo70CIhm}fGjg0 z|BO$8&w(!iv_r-(z;D1G95;LrU9wTgk6F@yi_<=M4 z?KoltFdE1La)Eqc0#FWA0+Rs9f5aAG8*n*r1@Iq^8z}-ZFc26FECiMVXxoto1CYf? zw8u!)V#=Mj@Y3kjbbEfQx`nfFFUM0kqF3w9jbp zWAv%O>A;!5*}(h2*TA>H_W+(5Qx72jF=&f1Xp1qhp<^BZP=+xm!tEkT!1Pvh)CCodsEEA^ofk0NOTd6L2{26z~dww#h=)4s_yevk>X(c9<)VJM z;7%_1k(&!ZF1bZO2`~{T2P%QtzyhESSPU!$Lcj{38CV6Z22KI42X+9EP41h(+rYcP z2OM6!49GwkFb+Vy@+JVtClC4LO#-F>2LjUo)HiPyFbAjw<^d>29?Fr2a^#^Lc?SW@ zfF@u$0J-FWmw6GO16T{7&GL=_jslJWAfvo9fU|*ff%AcjfNj8bpa-}LxE8n#xD&V= zxEFW;0N3;W1w0F&u6dAc9_pI+4)7kp>iRM8HSitq1Mm~@3&-UT0H9O(kVF1JU_ZbP zpxyI5fDZs)^G5-h0NOu47eL$Oj|U*He8?*w^2(nKKtB03z+7NH0NLa>0+2;MWRVY9 zj&W9ZGA%}c$B_CYLKMjB!@*#)(OMuM)>_I-{kPkWJUk}^}+yX!j z`H(~YL%<`z;{fE44>{z&3_v&XUk4zEe8?gH6W}x8O8|1nXL9%r02d4N0OU{rITRQG z6JQ0>fRVsx0CFgR914nn5}*ti2kZ~j14jTTYXRD+0A(t86hN5@o&;V1P_6=$tKfa$ zQ{Zy|Whp@W6rel>{{emle&@JC4uJd%A>YCf09h46R)vsN;fVlbRd^0?E&zEIUIttZ zKt_d-Q6Xehcn5G7a1U@l@F0M^i+ErJkPDzai;96#pd6?Gs(>W`+N@{|&;hIi&}Kyh z90eQ;oB*5zAm1Wzun6@iLLG`AQzXe1L#D;ZtJn`9zv4_F2gnCd!D7g*_yAxca3C-p zm<7xMAkX6EKr_$+v;k{@4Zxwm;Q-1~+zmVod(1w02l54;V01b}-bp95b3KLU_b3FHK^bES||=|BKwEHwgVzzRTKrQllWRA2@$ z8>j{519iX>;2@w8fUHU(tI|~f+N-n^K;25C0P0kF3~(HP`jnmpoC}-}TnKChE(dx5 z=vnDCz^%X?z}>*T0P0uz1n@NQEC4+#eF1m_Kpjip13myy*HYB6^jqKu0PRtVx|XE? zXooTxKwZlQ12zC{Qsx1CKmb6U%L)M0yQ~B#1116$z$Bm=fIP|?0q~*>yeJC;sB_sS z;4lDnE;|`OJfz1FoH1ZyD}Z*~Uj!r|6-WcJfujG{)Lln=S+9Kpezw5@Y3c6nmfWz}u#4{Q z4rxhgkOo0QLRvbdK?FerBqSsR>6A{Dkhz@sXWsQ*Yt}mN;rIRApZk88S!dq0q$Fhs z#SG=lP_7EqsYy?!u?6p!JIF5_;{>OXrJSAli6Ar%A7gi+DRD2M>B)%xLfuQK4nvEf zztGZ@#oM8}3$2ECLu=E7*0iG|It=}k(a01!gRhy(eB6Af-a^;2k3eCt=yhfu6$j6z0albQESsVRjT&iD=wbm~O(F(+YEh=_gD- zVci(WI3}W_u*Jw4whH}(eTQzswy~4F{K_9(;X39CyURWP=D+-Jcozf}YvJvRozPuH z-Br|GMcq~G&q%&NhKduI%v5w)@p~@wItaoOk`uQOZocqP!Z2re72IIBx5DdU=J0m- z-Eg}IH&gg(%n@#maC3zF?eN1K=On-JJLU>ESGc*t%@qDu5L8M)8gySN3)#s-ehN{P zQpi#%1~XRroY9QMT$RjK$y}A@@D1*-lD~H4w%wD+>O=&?ldeVn}3}i6F7>SIPXR#Q4RKCIEAc*(~^G4*tcM;*P zBD@!&_Xxd5m^C7jXuKKWwj%5|!t4?D8{xf(Y0PB_W{lXvc6M=rJGhyMhd~e-k5r^3 z17-2skyWXIIU)x!gyHBfaxLpv&qj7~kQ4arNWUHV-*4+Q@;NX0hc~?0XqblIGqRba%z9{oW^+117emlx4N^E-9fayM7x7%cMxrkXm=3p4x)W4(c>^jv^k>9;fWx|95LpIF-MF!V$2a^ju>;q zm?Op;qm?OpN8#jK{fMLi^5FR zs#1fm`IhCZWK9rMZ$@XjVxH>esgWIB)hI>@N-+U{zQ!Epu>dz$<2CkE!wuJzyXFrZ z;TXSiDhO)XL#?9dzSbv{W+)Sx%$Ix>1hpfni{5KDqzQ{y#|FM*3*M>|j|3zl3C-!k zr*x+moB5Ib=&{bBAgG%dH&QnvnaPHKZ(Vun4#(c=+FLyt>&a6unkrOh3TCf2pM@;p zPuyv}f6zreJFLGIZ`Su_{e%1x1P!Xu7`N0w)&{MDprKwG>ZPGx8tSE?Hye7tp*|W; zV>)i7;brdgkjFd=f<~dp)yVHQszGgLB2yzfZe+)eR`CRxJRLNC4|mnrpK0u0Xe>)( zSsKgI#Lk-(p%^8w^Cm->z$DDxM5d;RNJj>IXHB!xfj;!5KZE>#h33Ib&HPR?x7bYH zW;$+W=gsWAnHihed9y1#;1RMmdmaSM{h8(wxZmb6$lKi8%@?o;Gd5oq1TEZ0i;i^0 z{kG_i?py3f_bqha;+G(3nG{)DX2HH&=42Jy*ugG-2!d8|Nl9wbV#Zb{xy)6rb1Mj1 z=cOd})w(R@k-zmDbloPv-&Jkwr%gk2-A31KT3|12++`a%+ib_%ZRKwJIYSu6NDgzB z`}pm)PkF)Lyv952Lim9H@e%U2%ZwS@nXz3S@>2+R*3O-^le=9R${|;~0er(AZUjO5 zSeUPU4Z30X?PoHZdCbQQ?KiLqbF|lC`|tUIz3k&xe&ZY$xWYAVa)-Zo6$Bk*?+}lK zd`t>bq5lr%=^%fH(zt;RHK{{=8llq;Eoe*&vPbYC6aP{-rAfsSVBcouVXyojduNl1>lI@v*|ibN8FxjNORE)B4gPMvViod#f*PG;$3mQLfCz+|SfkhSQ$ldPQ% zaRiw=$=pfiPWtbp|4x^<%1h+z^oDmq(D^++BsOtLKw^?2bLS$|;xlyCc^CHB#hrA? zMmQ~zxr@wQy3><^jN}XC?lKYmcagixSIl5B-?D<$tYahcce#kXUEE}s+vvN?L!R(F z2)e$H3|$iAv?LqPeJ7GTAWIlqicI)?J8?mS-bYaY+d`~cDm}jtG>JHyX$P+ zeAflY+Ev!BvUZiVtE^pR?Yfz5?7)3=eHjFwx}{Ic;5I)U%}VU%(>p=XP1oIY+)d_g zI_{R74CEvaa(634QRMFS38jc2nyS>m&2+1W{N08kZ?`dwN6+1+F&#VWwhS4%$=z)` zyV=Wr>53D4tsw zGJmf>coPJ@)1dR-GWV9bx2}8Zy0?ydH>MeK_ijUbRGyMyo9!#)mhh$9^5B)=hhUw!x0ci(52p|2VGzTsUE z^wWPo{rA&&Q07*|G$vAzsv*Tk(i{UAT8<1L{^GW9ytdz zpfU0ekavK*1KMN00bS{i&Ij1{fbmS?OTI$h0rC!zcffpfKVT`#*pGYz|3@y|=0F_` zoX&R4F;M0~0q+wF9S@RwP-W`89#4? z;XYr$0sahv!EwlmIR?A=!6h)u;4osSMosEapN2HSZU%S8{SWRzZ~9`U!82LH3RYvL z!JF8Mo(J#3H#*q;3_g$igYWT>C%E^)vJZaEzdd6>+@WF02! zuyIUgDsFbzY~~{SutjXZ48u+#=P)^k$vNyY<{IX^9Cim?4|~XyAQ&DCH!$4yIXodB zlZ=$4LDu0J$wD^5Xvrv+VUNQf1i^?Tl%O7c7|bw6G8(x@%wi7Tun;#g;#-!p61Os9 zJ7yTMm;D^V8zYW!0yjUx&5zLeh!?n%5wC;5Gr`FB_>kD>dSq5gQif1uA6bb=VyH$< z>Y)3PUFe3Lk2J%`ehkDcBh50>BO|}S9!5^UeUCiI{U8{XfWr8#QT8>;jHA9s|D$el z2fdHd)hKr|>Rk|wmUpzgqvahPm-yJh=)|N)=cBWei~JO%2*okSXmgB~e{^kH(3TE# zraR^sZI03A7%lhcuduVxx*olT^?b(`^genQKky^JagGaI;wm?|&7YWKv>l9o8U$a+ z{Dpj9)S@@D*v+*d7!!i~8DoYqc_~04-2a%0R3?flRL4AHbU4NxjcH9gI?{!1m}$&p z=CY6_m}$&v*0O<3?Bf8(If-vzjQnHdA0z*mM?B#REYR^GAlj+J+8H+nD$eUClCvmhAfHpi8vB}19da#mr6arQFK zKE~O@xS#l$!yMrlzw!rHxXvx^az6;h$00dsa6{uWVW#mp$wPj;J-$3q#LxgUj5ou0 zGmLjb<2%un?hIi9`W~o&KgA9vB&HyGo$wj6*@K-;e4osO5{b+ct5Ji7w8HIAlzU=lK1J?{y%@>} zMl%+3Oq|SW^KTGLl4;V1#3nAO$w3+9 zoD@bS!ypXVAkxx=5xKKTvrf?&#f$UQ~wDIXD!1o*uv>BvYHvXhIvMB#g! z(wJtnq#Yg6_mofh99>VD$W*2?3%RDuXAw);gubVoLDnf3xs1$HWS%1PlzW(Q$`hUk z!IyE6^UH*MOfpj9#=lHYCbFXcFJ=C+GHn@)&b~a(iy)Yqicir0)ZWNERpzO>o;r$2 z%*5?Ym3!&}79;o633Q| ziXqRm(v&BRN<<>#v^Ml-5JMP_oYTfI9(kvI$ydldZ8huIh^*6OohIuvS*OW5P1b4t zE}7ltu38718;0xu?g_ zfW|bVCFYpko{`8qeFk4MmxV0mTUH?R^zYfjQBLw3=lBD+GTp6AzlqzJ5khk8c1Bt< zkeO`AIwKGHk$FZ@qNqZ3YEc(?XUIE4-Wl@Fkavc>GdePwr5xg35X^LgGwp3=L;9ij znVXP#rpz<<@e{{5%kRiN^9t9Id*&T{moxuD$1~ps!K{GyiA5IN$1Ly6`h?Py$9>GI zgq~;BrxC4bM=#`=HITuKU=(9;E3;;^j2*~2OV(NYIDpw^xrbT4lUe$nrSDlX&NA<; zhde>ov*exiiZ{Fqg0J7>12Q4s*LwR}Uth1}SNxgTNhpjNW|yM^6|sZax}V*E#^`>w z?q{24c3XPV2Q$q!(`+-%9>zDUVm;rng`JpbwwY#|X|@?=n_;#)nSC2w&wjvD{>x;J z+2)uN2e&gP4{l_R8<|s-5|pAW=9(k#oXSKY=Nvibn01aDnbV1`bVuenGS88Dj?8mD zXExjU1D(yyg5R0z&&-{GS>_((1gAO6d1Rlf|GD~~tN*!j&y{=bKfLB`5X}3C_#{Hl z^UN|Y6~&Qxo;#TrLp5qs4}H&TjNJ2Nm^XkS49C698;4x;CNq_VtVOT$+{!$+GS98d zb1U=oJWtQ_&T)ZDT;(Nl&T}X8%>0cz`Q}4n6PE-eCMhz1Q-oT4#w>PW{`s-UMmRd3 zFY|nv=j(dDuIKA`{z$$+?)ej$g52}JLiYJfaQE|9vWE2><##Ug-#a(?llwg4X%H+3 z;R9q?pxXs0Nke+br3by~i_RD5cY&M>reo#>b8y=W zWL_Zi0+|=cyg=p!>(KdvdqJ=;A%&=m`4`S-H|}fUs~}kPJ~A(I+lzF)NXLuPkrBBU zWhWPMFUn78%29!E%&{n%_Q<=aKZ6*;NJcXjH?m0PMKUjvd664g^c`E+j!cVukBjzk z0C%!T*Na~8H?R3O2o~#k@dx~mkBExRWI__!{#pnTOw5qW2|kWr>-Vm}!Zbmbl9$ z=lSpV?PAG8p70VgEiuy)Gc7g4(vL|-W^$05e3)TrQA*%$mPS#J&d9mcoh;S+QhArk zyHwt#Lm9znbiec)7P5q8xRa&wE|qtwyi4U>D(_Nxm+s~QZsXhZ==C8@E4Wx8Lc`(%)sZ11Aka@Yx%Vl0J^YVs##&mSITxZMQ1;Glxv%;TQ;agtu1v+1$>lM0Qq3ac! zk$uI_$i3nhbh_d=C%D8_Zg87Fc@P9E&9E{BGOv_*rOYdHkPDr!)cH#NuB?EpD{E5^ zIafBL1+8gEABHoN*|_1A3s}sztY9_k*oe$44m^Z*$F1Mj-PVnb*j-MsI8NwKflKY_0vQ{R;Q8 zR^Mx7UMurjJ+Hlre%C(ZC4VFLTDgrMtb31y_%_!iL(l8dkRJKhMI!GydDpp-b-G^H zn5MXqb=~O6K;&IFj>$}AI__oNT;?PHx()2cO{~-JI$77rx=z-0*D%{UH?i&>`d+8+ z^|6RUJY-!j>v~z&%er3H^|G$dL{{9;df(#uR*YsjM|c_p8LB|`0 zGafx|aOWH3-Y|~^$h~0+vTxXgd)csq@7cp2=y<~;{(I*IuXxKl|MaByNK8`X+$iJ5 zT;!z?MJP^5^u4hzo#;w;dhr?k8N?9e-RLGZjzP|ia&GiJZv2)NtY#e>*~~U}BJ;-I z`6mdzOGhZJ8Os`U^_}iF#YW~$GH*&jDl+5dHsz-va&MA*(P7dSu-6BR_GFqa5cXzj1>nL9jU%afpYz*!(fca2K21#b$T0 zS>K!8#paTf!MvNpsD!+m<=rgrW_dTuyIJ1N4bk`J>1^i$_P8Y*QFP!7+{6}{x5&KZ zJM_H8ZEx{+$Cks$z2#R+{=~+JmwiMgJ5eCGUA=BInnjjf)u70dfpmA zG_|RR-EEa;YiB;C7k%i*K*lkXmB_kP)~(;M1+#74#SiFvtG>6&xYfK{FL4!JZ0s26kj53)#s0l z;*y9YBqt5&G1D$H?J~nIx3jAR;ke&jRj7_RcGaUHP3Vlf*)TnM^!dZj z+zWy|=HFvqd+cUUFQ%aXJu>gn|DJ`onLXdJ1-bX^;s@m3V;6g5-*bvHoaZ8!c@qSC z`h84(&A?JW}+ZPkaMq$dn1XV2DPY*{`a=0H(xLgH?vpPz0+_rdu84`7n%3E znZ29YhK~2@c(1H`_hat8hdGMed)>|6M?vtTj6W7e4?o)HkKgbkSA)Qa!9H{Bi$_At zvM)7R@D1QIY0qkI3IV#}(_eBs*RXWj^K@7pI>@&~4u}okx-rctlx3W*?`*glf z=ljgCZx6!kbNl;#;~IbQinl>vykP(P#6sTv^6r;+|HmXFH~G-{ex2_xPD#oTN*H#q z-wyW6yuUrZm;Ea_!s8(LDLHQIr-tb1r|HQ2lgvLY;ak?B`=50G)Az{zliWZ3#6f;R z|3CfCA6(%&x40Vw2joAHgp{NqJz2<(dq3db56Ez!EalPd0k?9XE)8f(b6U|BcXMDE z?&N?wIp9tXxRV2mSjuu%q4NV9*u){seBd~4KiGx-xRrxL7|tlhAoIbE zY-I=E^CSCl-veC22KHP%V^kX1{vFF3G9hU8|Y=>n#JOzJG9Jc?%v)IgObn#1S z%Fzbh{<4e%*zGU(k@*+h{qmf*L2x7%agh5+LOw?BBPr0~k?iCmF9j$}F>0aHBi=dE zo=$Y52fgXbXvQ*uukl?SS;!Jr;6{(EMbAg}a1?iVMAjp>xQon3WIiJE5&J%3#v`wT z;HZv|>iDRvM`b-~?xX2&mq&GeRPLj4AI*c_kIHy-JZm_?UqNsz4Q}LEL)^wOw{ffk zW;xaiw{gsE92?Fk^m)tEp)Igd9%@5kjmF7I)9k9X!%bbnm;$H$`cCN6Psn{j_a}6JLhche z$VG8VQif2%sD%6{x*_k0z6?OuC*1pqk$i#sJ|V*ixlb&|?oO=dJLEdCgYVgcGEZFO z39_E}3q7BZ`J~JzWj+}TGoFk`Lb4*~$=u|_cY3l2GM|+Bq|7H}J}L9ba9T1H-JR6g z$v=bOR3eH}o1RQY*QaDYrR!4*(DA8_Y)0-=JK2rgr+!5CQ$n8ljdNVU-JE(I1gB%; zMoxR@bP`gM27RB-NC65X=V=*FM-WYQYEp;#w4)cJ8H@WkE$iv2Oh@L^bCCJ8`#8Oc zt?2l)j!(;adLQOKeTXB-ecC~sei#J5$@p6#^zd6>=CPM6ybFRe<~S1};XHtp)?tn_<~U=HGe02H znf?6C8Lsn^e|UqeXW!#PWIh`gna?IBEAHj2dpYY~&dPeW2*q(PXWh$LxzARh88V*L z&ligh4 z4i9+DGydi^Z-d}`KtetyDVfMlF7hJRd9$21%Xzb$*ZKLnbfPQW>BVRCXAnae&M55Q z{5<45znE`X!D?hazX7{AZx`q7;`}azIxpkzX(>l5{Lb(G%S6xh!N`?+907xH007tC})-xr$V_b;@i17^C=jh^&jBwz3qbI|z( zySuQ2RjkDf7tC;B3vTJcLFBw}j9>YKYuw}x4|t3jE|}q>+!s@mfy`t>){C-Ul=Y&l z7t2$LNMexvVlC|AVguUK8@Fy@McFUPeo^*|%h2^jc`yFRPsn{y?u&9? zJi%$s@;evN^&crILodCCjqzVa#vuKtgYh)*KSaWy$bkoT(FxEe_eHK>h_uQovDt6k_rKSm+T z)rm}DIy0G#&abX!JMQ4BJGkl&uF81T9bEkbS+8E_7BXLz`C14cAm=qXugQ5$&TDdB zlk-|Ce9zb1_%)qeD@Rj?;qQfOKl306t|z7-?&P}6*JZvg^L5=`|D4fGW-4-D*Z1`~ z$bEf2vR_}vMmDpJot)z)fAZfuk9mQ9uj}{v+aS0RkA%p1L&h6f$w6M+$_=-2!>!zK z8#ijumJZnMjZf)8Z~8I-d2bA51ajVx^M-Hm#zK~`jFrfIL*^SY-;nvnR&;*jSrFVz zK}nk8cW(MKH{H)ov)p=*xFkStw{(3=_FLI-Gjqg{QYt3Ck}F!8~no?-UY#JId6YRY~;Ny?`?T+ zC&hfX^HPAq6yp<0<3?^*Ae;!Ik@lmv`j8a~Rq0{LUX-;X1d1;O_e*A{pMfn}&>JM%Q<9Qi4**a96i?t5K6WG(@hu z&1gw?+{WFhOlKBza2t2s#@!{@^If-bcMUqftKYkF-u(qL-#vjFxhwPC^IXK=e|N8; z|35>J@lW0T*^Y7eoj?7VKi$>6kJ0%(UEeE>uJ4sc_ItIcO9SM-C-=P;bVc@iz3_M5 zJvVc25MQI?d#hNBp6_j88#~#}QGP|Y_hh_xlRG@%5q5a*MG)NofW%}a2f4{dLEP~D z;*>1~U(HJXnF- zdSI3ZTiJtKd2oP39KjAAnCF3c9$dk#Jh;VO?gzocIQV<-VH(ntiR|Pe5BVvJ&L39A z91qR$&>Rn&BGbcGw52!07|9pd<->_gW-i~bfW_$ap&lRp8w8Ksz$1M=`X3*W1eqSC zA}tw^>rqXHvW|1u#bbZwaU%Sg$NtRYl*s@_k2aoOGaU`-oZiMWQTOjx2 z4s=HUkInFSAXAvb687^8_k!SwtWOe<5br+u82O&~#-3y&Cwa(+@9c@UpOm8lvOm$s z6Fodxh~Iv)jFqfmJ>Ri~pE=A?e&rNrIL}2cbCuUY@Kgs+Q&WtJ)Wb|qKVt~P8O0aq z|LF?c%~L%-^$k4r&eK1676kq~cxJ|D?_np;-1xJkq`(``(qZ0bg)rYUxACkz-hEby zYShL}JnKexde95=KO4bl#xjA)%wsv5k>#10pPBjDDa`!L%+JjH%*@ZOag#f|4T9(L zK7XGNiA`MW=egX^<$f;rb9eMSE$;fcyw4+PiCsS*&jP&t+`G?x8_%EcH*WJq7II^! zFN$N%7geZ^Z{bB$Z^-fbHjnW3 zYj3~t`)|zq#_zt#N!-f$!y%!8@qk8h@~uJ6Im!EhXgajXxpKgq0Y7i1TJsHVIc`8zwD5_AMTGXWhjro-B z^x`x6Gl(G!XCzY$T& zozQW-8ORXNtnqFIA@Scs#`pyZM|bf%ptJZr>BC^`D84S@&%*5SSF#4b6@N3^*va>t z=QiexZ!TvYlE7RE%$2}g3CxoqDJe)zIx_GH^=VB%rZAng`27TWO>l&>T;nEp&~t)& zJmg6blF&>E{cgf6ce@B9V6z znIq9l{^1Spf{?`COZ*`j$%Wrf9EEQzNf+!ViL6QNB#GZhS_D~=nk{J!d=p8{n6x2H zXpTRZ)VxXUH>pfXKchc`uXs!W82Ze1pl#AyYD$l2yaI z$-JA)yUEO-tUI$fg5OJ?gtWN3?%bxemjM|q-aJ9S~HyScq7F+^qImN zDZG*5DmRcn#Vg)oKPl}eWkNp2O{dgTN^hmCfOk^%VF31%awCU0!)31FhEuxXl zbN<5br}X>&pBW*k{C=ub=q8o>O4XAg$eL;t?kSbbsV1?2HLOMcR2%SKD(|JzSE`G6 zHMGqwWFsee$dB(co!-)wpcG}1Bb^@8RVE5Io31^b=!zNAnIWAS(wQOM0Axz1^K?2- zr}K0=Pp9*A6Ok?5e*OtU(tm(kPH*q&n=lr4pI+Ydr@0@5WJp0?N>YYU!l;CPGq}kN zZO~~3oo0|HLl1P4!P^^sAB{CfhrTkFM#hZg&{f7(w50=``4rhQ_U2pGv4ii~gZ*SYz#)D?o{Sf` zgj|{ahxaq-BvWeAkrDl5(oZIDXVOn5{bZ^^Q(Dj(cazE8WO6r|`Z18v$dJjKnY@$f zQ4o^(J(7_db7b~iX14##l`&K180z4+GuwCO!OTLBnYZ#IKXEV!$r6i%q#+}6W|1?C zd|4_HiQmgojrugg?`CO%%vp4oMQ2&$%sUv?`5q^0~*temUt_xS+Wjg6k`~Vd(AqVg)CtiEAf6-?`QRXR_|x^epc^i^=8(K zT;~>dxsSgyvikcX>)*WQ-ykGgY!Z{6Ok~BkkS!N^u*YojX46kL{baMxY`V$TiLP|V zKC{_pw*CxaEEAZ_RNQ+uyUC`vZ1Y&oE>3a<*|O^Cuk5HS>3 zuUy{CrRQAsohui4(QB^Z*ikN><~oR(a_J`bhsc^cF7Zi35|WdOwCE@IC)iW&a#SFk z%2Y?@+%o5GLUUT;+sZ9}ZuxWDXYLVrnJGQWmo!D*eQ=H*E7lM#H^5tp4 zF!Ye;3+yV-1l(jEznjPJ=JC6E%$UdBoL9Gbb(=Rg#R#Jkkwl||yz=E;ioWx%Vh!stXI^vW z-Hva?KT9MeuMBx*$ZL;zuVN>8Z}Eti{KFgM$rpm}DPLlek^(vMm7o-5DNhUyXiQV| zmajAY7|39T;@iom-+bQBr-OV~@K$~|lfN`($#0+eThW#d_?`TAo8NBp+im`dOko-` z_?o$V!!p)lANlPgzkTF4dw%=Pe+cjAKh8xibB&uk)2PpyWHbBZ-Ws35l={=_lZRu;v##YG^8gJSusbUaO5pikA~>IP)pj- zj*iG&XcRIQlChA^3r%Mxvzdp?g>+fS`~IVskiyUo@qS^qQ`jtplah~u6rngJ z(Pv?O7S?0o81z`U22E*!J1E?i?(}CgW0}AtmScy79|R#q%F!HuriedNqywG#lpge^ zFXkxXc8a*2B40C?`7C558`#8FcCd>>xSb+yr^rbzaEE(5YVM+X zFRJ&VdM}zCvllgMQL`2`Ytfq2!OawPGeyl^)Z9f|V-H2$Owqv%VrFq56=qU49zLCK1=pd(%AMh^xs0zH=;%LFF#C9;=X z$P$*}21=U4KaV4%q`W14yCpAk4Skoq%Y7apbE&wvXzpply9umB9>zBrB<<)^=xMk`#8WM^jqp27r2BjO1Xzp zfANa9L5TmTGo-X0OUqc=O_bJSY1vBWqaf~}bTRzhQCf!5V;ILoWGU^v(%viWz0yZG z&Pjg5+oio-`Z?Y#?ak8OEaS~G?_)1z65!1;DbY=t^mxCF_se*{jQ7j9!!i}9NDXRJ zkA}3PBc1saIm^gdW-RttW)gE)&v$G=S7rR2ROScVV;T2Y#yytNSD9m6=N5Od%QALZ z<|!|5k7ZtCw`D^xM_GBxhSHi*tUwQCp9LZ1bXu+u)u>M+n$nyOxW96}vGa0vUe3pU(t2BbNtR9$XxCpWDJ!t)HmawgAo!Mmjon6=1`r6 zh7&X7Dxs?}5;7SjAd4un9ef9ziFeCy_VQ z_Y!&&-%O~R41E!Vlz)#8iOol(ATI?dOff#8H06-Ly!_?mFE4+2otAG!TXb9AO_cu> z9hdLLXY^+f<|wbv@;kT`g!qs8Ln>s&?^N(-D!A_ot2uo#7|$eRs3b!r87j$8X&wt$ z%(wVEqS7i3aytmA92cEeu8BD+&q2=0=XuGyASA-~5%D2@Ok* zMJYik%Hr-K%n{K7c_Vt#hkks{P=+%KnImNO&(jErkTJqH5V4L;Y+*aQ_=VR&NTl~8 zy&viQ$gFrj()~o5C9)uTjI4tFMb@G&`i#_PWK-Nwq)d@IjMQPI4kP7?lqGTu`i#_P zq+F2;kt=c;E7^*UBISwvfy12TcmCjV5E7LUS)%MU%3h;%6XorwK@7p%QQnI3R+P7* zycK14QQnJM!+O5M>``Wq@>bMte&!e_IE{Cs>?-OOck%s2J>qQ;68#bJv9stTq$dyg z(NVOHqTRcH-bP4tHQYdSZRTPJ(W{UpT9)YVaktU#Hu@YFxWrX%aGO7Qz~dk!=0jo= zmjomxDJgJ2F=?^C82gK{znBWRlbDgX(-@t`_?;^LOcgn+*kP4!*in^%495Lb8Ov1k zR%HgWn2i~#n4yY0sVQJ$|UTrsti?U;{B@gSb*=Ys(Grqld3=R69@T)WBiK!RlUM>?6K-y?(sLT`8Nou z7J?qD$x}_9YVuUmTQ&Dptqh^)uv$3PX+m>a(FQ$Kb4S&7VwctSa1=dMyU88AS?wWD zc#bZr>7v@(Af$RgGEyQ#bs4J5P+f-VImk^u3SwW?i(zNgdoZ1?TnIvHn4?BEg1<74QNRl+S7@ybYnb=@!NIwBV(OkImH=#7j^Vn zN6tEazm87pJmwiM`8x=y8-g9zjYB;2S~msmvu-A`l7n2-rXOE3m-#GY33{t*&vkWI z*PiPh;t1xgYu>u%t!v)8zjK|3Ji&KT*LPC)6>rgFJvr(nkic^+q!d`=~dIIeg1^Y+*b4tDl8}xas;uao6?rUcV21r@k5Mo3Xwb z>#t@V8`;b@{`-y7oW+dw|KJK{t*`s~=B@t^Zl%5%8@QDQ?zw?`ZtxL0Z;+aFWJHDr z6$mGSXzI}#x7?s3UFgpshA^DTOyw(PvItol$l5^G23v!WhTdqHo4n+w5S8$|4gGFI zzuT}IJu!bnJ8w7;-%Ufm*>E=VSioZR*>E`<*unSgVIK!@_YHr;{u}D1;UBocMgi{= zi#Q}F3)!*rM)EZ(fesq!pivZ6s81W((+PPS{lF29@hhiz9fUO2Z{x%yB?UTeZ2rdH zXq*#&S2Wf^V;wXuLUnpD3V$y&Ud1N1Vz$O+Yizd0hwxtG_Y$8V!yKFL(+00`Bi}{un$k;@#CVFo2 zC<0rZg{h)H=BC1=|a}B0kbzXU(?H6<7N=j z%+8u6A_;cZtQcW33WD-IhJjZA;y@)NRYp8H&BN9M4pyGmAOQ zVWC_#U0K)Je-GI|+h-s%dTyTs z+1r<(6lJlu_U35c0(sl_qz`&;|2ab#&M0JVzYrPQ%h+D$?KkipTd?EyGPgg08*2YB d2v( diff --git a/MacSerial/UserPseudoRandom.c b/MacSerial/UserPseudoRandom.c new file mode 100644 index 00000000..fe03d527 --- /dev/null +++ b/MacSerial/UserPseudoRandom.c @@ -0,0 +1,71 @@ +/** @file + Copyright (c) 2020, vit9696. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause +**/ + +#include +#include +#include + +#ifdef __GNUC__ +uint32_t arc4random(void) __attribute__((weak)); +uint32_t arc4random_uniform(uint32_t upper_bound) __attribute__((weak)); +#endif + +// Taken from https://en.wikipedia.org/wiki/Xorshift#Example_implementation +// I am not positive what is better to use here (especially on Windows). +// Fortunately we only need something only looking random. +uint32_t pseudo_random(void) { +#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) + if (arc4random) + return arc4random(); +#endif + + static uint32_t state; + + if (!state) { + fprintf(stderr, "Warning: arc4random is not available!\n"); + state = (uint32_t)time(NULL); + } + + uint32_t x = state; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + state = x; + return x; +} + +// Taken from https://opensource.apple.com/source/Libc/Libc-1082.50.1/gen/FreeBSD/arc4random.c +// Mac OS X 10.6.8 and earlier do not have arc4random_uniform, so we implement one. +uint32_t pseudo_random_between(uint32_t from, uint32_t to) { + uint32_t upper_bound = to + 1 - from; + +#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) + // Prefer native implementation if available. + if (arc4random_uniform) + return from + arc4random_uniform(upper_bound); +#endif + + uint32_t r, min; + + if (upper_bound < 2) + return from; + +#if (ULONG_MAX > 0xffffffffUL) + min = 0x100000000UL % upper_bound; +#else + if (upper_bound > 0x80000000) + min = 1 + ~upper_bound; + else + min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound; +#endif + + for (;;) { + r = pseudo_random(); + if (r >= min) + break; + } + + return from + r % upper_bound; +} diff --git a/MacSerial/UserPseudoRandom.h b/MacSerial/UserPseudoRandom.h new file mode 100644 index 00000000..8ed5474f --- /dev/null +++ b/MacSerial/UserPseudoRandom.h @@ -0,0 +1,14 @@ +/** @file + Copyright (c) 2020, vit9696. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause +**/ + +#ifndef OC_USER_PSEUDO_RANDOM_H +#define OC_USER_PSEUDO_RANDOM_H + +#include + +uint32_t pseudo_random(void); +uint32_t pseudo_random_between(uint32_t from, uint32_t to); + +#endif // OC_USER_PSEUDO_RANDOM_H diff --git a/MacSerial/macserial.c b/MacSerial/macserial.c index e562c7cb..b3c6386c 100644 --- a/MacSerial/macserial.c +++ b/MacSerial/macserial.c @@ -18,76 +18,78 @@ #include #endif +#include "UserPseudoRandom.h" + #include "macserial.h" #include "modelinfo.h" #ifdef __APPLE__ -static CFTypeRef get_ioreg_entry(const char *path, CFStringRef name, CFTypeID type) { +CFTypeRef get_ioreg_entry(const char *path, CFStringRef name, CFTypeID type) { CFTypeRef value = NULL; io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); if (entry) { - value = IORegistryEntryCreateCFProperty(entry, name, kCFAllocatorDefault, 0); - if (value) { - if (CFGetTypeID(value) != type) { - CFRelease(value); - value = NULL; - printf("%s in %s has wrong type!\n", CFStringGetCStringPtr(name, kCFStringEncodingMacRoman), path); - } - } else { - printf("Failed to find to %s in %s!\n", CFStringGetCStringPtr(name, kCFStringEncodingMacRoman), path); - } - IOObjectRelease(entry); + value = IORegistryEntryCreateCFProperty(entry, name, kCFAllocatorDefault, 0); + if (value) { + if (CFGetTypeID(value) != type) { + CFRelease(value); + value = NULL; + printf("%s in %s has wrong type!\n", CFStringGetCStringPtr(name, kCFStringEncodingMacRoman), path); + } + } else { + printf("Failed to find to %s in %s!\n", CFStringGetCStringPtr(name, kCFStringEncodingMacRoman), path); + } + IOObjectRelease(entry); } else { - printf("Failed to connect to %s!\n", path); + printf("Failed to connect to %s!\n", path); } return value; } #endif // Apple uses various conversion tables (e.g. AppleBase34) for value encoding. -static int32_t alpha_to_value(char c, int32_t *conv, const char *blacklist) { +int32_t alpha_to_value(char c, int32_t *conv, const char *blacklist) { if (c < 'A' || c > 'Z') - return -1; + return -1; while (blacklist && *blacklist != '\0') - if (*blacklist++ == c) - return -1; + if (*blacklist++ == c) + return -1; return conv[c - 'A']; } // This is modified base34 used by Apple with I and O excluded. -static int32_t base34_to_value(char c, int32_t mul) { +int32_t base34_to_value(char c, int32_t mul) { if (c >= '0' && c <= '9') - return (c - '0') * mul; + return (c - '0') * mul; if (c >= 'A' && c <= 'Z') { - int32_t tmp = alpha_to_value(c, AppleTblBase34, AppleBase34Blacklist); - if (tmp >= 0) - return tmp * mul; + int32_t tmp = alpha_to_value(c, AppleTblBase34, AppleBase34Blacklist); + if (tmp >= 0) + return tmp * mul; } return -1; } -static int32_t line_to_rmin(int32_t line) { +int32_t line_to_rmin(int32_t line) { // info->line[0] is raw decoded copy, but it is not the real first produced unit. // To get the real copy we need to find the minimal allowed raw decoded copy, // which allows to obtain info->decodedLine. int rmin = 0; if (line > SERIAL_LINE_REPR_MAX) - rmin = (line - SERIAL_LINE_REPR_MAX + 67) / 68; + rmin = (line - SERIAL_LINE_REPR_MAX + 67) / 68; return rmin; } // This one is modded to implement CCC algo for better generation. // Changed base36 to base34, since that's what Apple uses. // The algo is trash but is left for historical reasons. -static bool get_ascii7(uint32_t value, char *dst, size_t sz) { +bool get_ascii7(uint32_t value, char *dst, size_t sz) { // This is CCC conversion. if (value < 1000000) - return false; + return false; while (value > 10000000) - value /= 10; + value /= 10; // log(2**64) / log(34) = 12.57 => max 13 char + '\0' char buffer[14]; @@ -95,7 +97,7 @@ static bool get_ascii7(uint32_t value, char *dst, size_t sz) { buffer[--offset] = '\0'; do { - buffer[--offset] = AppleBase34Reverse[value % 34]; + buffer[--offset] = AppleBase34Reverse[value % 34]; } while (value /= 34); strncpy(dst, &buffer[offset], sz-1); @@ -104,142 +106,84 @@ static bool get_ascii7(uint32_t value, char *dst, size_t sz) { return true; } -static bool verify_mlb_checksum(const char *mlb, size_t len) { +bool verify_mlb_checksum(const char *mlb, size_t len) { const char alphabet[] = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; size_t checksum = 0; for (size_t i = 0; i < len; ++i) { - for (size_t j = 0; j <= sizeof (alphabet); ++j) { - if (j == sizeof (alphabet)) - return false; - if (mlb[i] == alphabet[j]) { - checksum += (((i & 1) == (len & 1)) * 2 + 1) * j; - break; - } - } + for (size_t j = 0; j <= sizeof (alphabet); ++j) { + if (j == sizeof (alphabet)) + return false; + if (mlb[i] == alphabet[j]) { + checksum += (((i & 1) == (len & 1)) * 2 + 1) * j; + break; + } + } } return checksum % (sizeof(alphabet) - 1) == 0; } -// Taken from https://en.wikipedia.org/wiki/Xorshift#Example_implementation -// I am not positive what is better to use here (especially on Windows). -// Fortunately we only need something only looking random. -static uint32_t pseudo_random(void) { - #ifdef __GNUC__ - if (arc4random) - return arc4random(); -#endif - - static uint32_t state; - - if (!state) { - fprintf(stderr, "Warning: arc4random is not available!\n"); - state = (uint32_t)time(NULL); - } - - uint32_t x = state; - x ^= x << 13; - x ^= x >> 17; - x ^= x << 5; - state = x; - return x; -} - -// Taken from https://opensource.apple.com/source/Libc/Libc-1082.50.1/gen/FreeBSD/arc4random.c -// Mac OS X 10.6.8 and earlier do not have arc4random_uniform, so we implement one. -static uint32_t pseudo_random_between(uint32_t from, uint32_t to) { - uint32_t upper_bound = to + 1 - from; - -#ifdef __GNUC__ - // Prefer native implementation if available. - if (arc4random_uniform) - return from + arc4random_uniform(upper_bound); -#endif - - uint32_t r, min; - - if (upper_bound < 2) - return from; - -#if (ULONG_MAX > 0xffffffffUL) - min = 0x100000000UL % upper_bound; -#else - if (upper_bound > 0x80000000) - min = 1 + ~upper_bound; - else - min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound; -#endif - - for (;;) { - r = pseudo_random(); - if (r >= min) - break; - } - - return from + r % upper_bound; -} - -static int32_t get_current_model(void) { +int32_t get_current_model(void) { #ifdef __APPLE__ CFDataRef model = get_ioreg_entry("IODeviceTree:/", CFSTR("model"), CFDataGetTypeID()); if (model) { - const char *cptr = (const char *)CFDataGetBytePtr(model); - size_t len = (size_t)CFDataGetLength(model); - int32_t i; - for (i = 0; i < APPLE_MODEL_MAX; i++) { - if (!strncmp(ApplePlatformData[i].productName, cptr, len)) - break; - } - CFRelease(model); - if (i < APPLE_MODEL_MAX) - return i; + const char *cptr = (const char *)CFDataGetBytePtr(model); + size_t len = (size_t)CFDataGetLength(model); + int32_t i; + for (i = 0; i < APPLE_MODEL_MAX; i++) { + if (!strncmp(ApplePlatformData[i].productName, cptr, len)) + break; + } + CFRelease(model); + if (i < APPLE_MODEL_MAX) + return i; } #endif return -1; } -static uint32_t get_production_year(AppleModel model, bool print) { +uint32_t get_production_year(AppleModel model, bool print) { uint32_t *years = &AppleModelYear[model][0]; uint32_t num = 0; for (num = 0; num < APPLE_MODEL_YEAR_MAX && years[num]; num++) { - if (print) { - if (num+1 != APPLE_MODEL_YEAR_MAX && years[num+1]) - printf("%d, ", years[num]); - else - printf("%d\n", years[num]); - } + if (print) { + if (num+1 != APPLE_MODEL_YEAR_MAX && years[num+1]) + printf("%d, ", years[num]); + else + printf("%d\n", years[num]); + } } if (ApplePreferredModelYear[model] > 0) - return ApplePreferredModelYear[model]; + return ApplePreferredModelYear[model]; return years[pseudo_random() % num]; } -static const char *get_model_code(AppleModel model, bool print) { +const char *get_model_code(AppleModel model, bool print) { const char **codes = &AppleModelCode[model][0]; if (print) { - for (uint32_t i = 0; i < APPLE_MODEL_CODE_MAX && codes[i]; i++) - if (i+1 != APPLE_MODEL_CODE_MAX && codes[i+1]) - printf("%s, ", codes[i]); - else - printf("%s\n", codes[i]); + for (uint32_t i = 0; i < APPLE_MODEL_CODE_MAX && codes[i]; i++) + if (i+1 != APPLE_MODEL_CODE_MAX && codes[i+1]) + printf("%s, ", codes[i]); + else + printf("%s\n", codes[i]); } // Always choose the first model for stability by default. return codes[0]; } -static const char *get_board_code(AppleModel model, bool print) { +const char *get_board_code(AppleModel model, bool print) { const char **codes = &AppleBoardCode[model][0]; if (print) { - for (uint32_t i = 0; i < APPLE_BOARD_CODE_MAX && codes[i]; i++) - if (i+1 != APPLE_BOARD_CODE_MAX && codes[i+1]) - printf("%s, ", codes[i]); - else - printf("%s\n", codes[i]); + for (uint32_t i = 0; i < APPLE_BOARD_CODE_MAX && codes[i]; i++) + if (i+1 != APPLE_BOARD_CODE_MAX && codes[i+1]) + printf("%s, ", codes[i]); + else + printf("%s\n", codes[i]); } // Always choose the first model for stability by default. @@ -248,15 +192,15 @@ static const char *get_board_code(AppleModel model, bool print) { bool get_serial_info(const char *serial, SERIALINFO *info, bool print) { if (!info) - return false; + return false; memset(info, 0, sizeof(SERIALINFO)); // Verify length. size_t serial_len = strlen(serial); if (serial_len != SERIAL_OLD_LEN && serial_len != SERIAL_NEW_LEN) { - printf("ERROR: Invalid serial length, must be %d or %d\n", SERIAL_NEW_LEN, SERIAL_OLD_LEN); - return false; + printf("ERROR: Invalid serial length, must be %d or %d\n", SERIAL_NEW_LEN, SERIAL_OLD_LEN); + return false; } // Assume every serial valid by default. @@ -264,11 +208,11 @@ bool get_serial_info(const char *serial, SERIALINFO *info, bool print) { // Verify alphabet (base34 with I and O exclued). for (size_t i = 0; i < serial_len; i++) { - if (!((serial[i] >= 'A' && serial[i] <= 'Z' && serial[i] != 'O' && serial[i] != 'I') || - (serial[i] >= '0' && serial[i] <= '9'))) { - printf("WARN: Invalid symbol '%c' in serial!\n", serial[i]); - info->valid = false; - } + if (!((serial[i] >= 'A' && serial[i] <= 'Z' && serial[i] != 'O' && serial[i] != 'I') || + (serial[i] >= '0' && serial[i] <= '9'))) { + printf("WARN: Invalid symbol '%c' in serial!\n", serial[i]); + info->valid = false; + } } size_t model_len = 0; @@ -276,46 +220,46 @@ bool get_serial_info(const char *serial, SERIALINFO *info, bool print) { // Start with looking up the model. info->modelIndex = -1; for (uint32_t i = 0; i < ARRAY_SIZE(AppleModelCode); i++) { - for (uint32_t j = 0; j < APPLE_MODEL_CODE_MAX; j++) { - const char *code = AppleModelCode[i][j]; - if (!code) - break; - model_len = strlen(code); - if (model_len == 0) - break; - assert(model_len == MODEL_CODE_OLD_LEN || model_len == MODEL_CODE_NEW_LEN); - if (((serial_len == SERIAL_OLD_LEN && model_len == MODEL_CODE_OLD_LEN) - || (serial_len == SERIAL_NEW_LEN && model_len == MODEL_CODE_NEW_LEN)) - && !strncmp(serial + serial_len - model_len, code, model_len)) { - strncpy(info->model, code, sizeof(info->model)); - info->model[sizeof(info->model)-1] = '\0'; - info->modelIndex = (int32_t)i; - break; - } - } + for (uint32_t j = 0; j < APPLE_MODEL_CODE_MAX; j++) { + const char *code = AppleModelCode[i][j]; + if (!code) + break; + model_len = strlen(code); + if (model_len == 0) + break; + assert(model_len == MODEL_CODE_OLD_LEN || model_len == MODEL_CODE_NEW_LEN); + if (((serial_len == SERIAL_OLD_LEN && model_len == MODEL_CODE_OLD_LEN) + || (serial_len == SERIAL_NEW_LEN && model_len == MODEL_CODE_NEW_LEN)) + && !strncmp(serial + serial_len - model_len, code, model_len)) { + strncpy(info->model, code, sizeof(info->model)); + info->model[sizeof(info->model)-1] = '\0'; + info->modelIndex = (int32_t)i; + break; + } + } } // Also lookup apple model. for (uint32_t i = 0; i < ARRAY_SIZE(AppleModelDesc); i++) { - const char *code = AppleModelDesc[i].code; - model_len = strlen(code); - assert(model_len == MODEL_CODE_OLD_LEN || model_len == MODEL_CODE_NEW_LEN); - if (((serial_len == SERIAL_OLD_LEN && model_len == MODEL_CODE_OLD_LEN) - || (serial_len == SERIAL_NEW_LEN && model_len == MODEL_CODE_NEW_LEN)) - && !strncmp(serial + serial_len - model_len, code, model_len)) { - info->appleModel = AppleModelDesc[i].name; - break; - } + const char *code = AppleModelDesc[i].code; + model_len = strlen(code); + assert(model_len == MODEL_CODE_OLD_LEN || model_len == MODEL_CODE_NEW_LEN); + if (((serial_len == SERIAL_OLD_LEN && model_len == MODEL_CODE_OLD_LEN) + || (serial_len == SERIAL_NEW_LEN && model_len == MODEL_CODE_NEW_LEN)) + && !strncmp(serial + serial_len - model_len, code, model_len)) { + info->appleModel = AppleModelDesc[i].name; + break; + } } // Fallback to possibly valid values if model is unknown. if (info->modelIndex == -1) { - if (serial_len == SERIAL_NEW_LEN) - model_len = MODEL_CODE_NEW_LEN; - else - model_len = MODEL_CODE_OLD_LEN; - strncpy(info->model, serial + serial_len - model_len, model_len); - info->model[model_len] = '\0'; + if (serial_len == SERIAL_NEW_LEN) + model_len = MODEL_CODE_NEW_LEN; + else + model_len = MODEL_CODE_OLD_LEN; + strncpy(info->model, serial + serial_len - model_len, model_len); + info->model[model_len] = '\0'; } // Lookup production location @@ -323,157 +267,157 @@ bool get_serial_info(const char *serial, SERIALINFO *info, bool print) { info->modernCountryIdx = -1; if (serial_len == SERIAL_NEW_LEN) { - strncpy(info->country, serial, COUNTRY_NEW_LEN); - info->country[COUNTRY_NEW_LEN] = '\0'; - serial += COUNTRY_NEW_LEN; - for (size_t i = 0; i < ARRAY_SIZE(AppleLocations); i++) { - if (!strcmp(info->country, AppleLocations[i])) { - info->modernCountryIdx = (int32_t)i; - break; - } - } + strncpy(info->country, serial, COUNTRY_NEW_LEN); + info->country[COUNTRY_NEW_LEN] = '\0'; + serial += COUNTRY_NEW_LEN; + for (size_t i = 0; i < ARRAY_SIZE(AppleLocations); i++) { + if (!strcmp(info->country, AppleLocations[i])) { + info->modernCountryIdx = (int32_t)i; + break; + } + } } else { - strncpy(info->country, serial, COUNTRY_OLD_LEN); - info->country[COUNTRY_OLD_LEN] = '\0'; - serial += COUNTRY_OLD_LEN; - for (size_t i = 0; i < ARRAY_SIZE(AppleLegacyLocations); i++) { - if (!strcmp(info->country, AppleLegacyLocations[i])) { - info->legacyCountryIdx = (int32_t)i; - break; - } - } + strncpy(info->country, serial, COUNTRY_OLD_LEN); + info->country[COUNTRY_OLD_LEN] = '\0'; + serial += COUNTRY_OLD_LEN; + for (size_t i = 0; i < ARRAY_SIZE(AppleLegacyLocations); i++) { + if (!strcmp(info->country, AppleLegacyLocations[i])) { + info->legacyCountryIdx = (int32_t)i; + break; + } + } } // Decode production year and week if (serial_len == SERIAL_NEW_LEN) { - // These are not exactly year and week, lower year bit is used for week encoding. - info->year[0] = *serial++; - info->week[0] = *serial++; - - // New encoding started in 2010. - info->decodedYear = alpha_to_value(info->year[0], AppleTblYear, AppleYearBlacklist); - // Since year can be encoded ambiguously, check the model code for 2010/2020 difference. - // Old check relies on first letter of model to be greater than or equal to H, which breaks compatibility with iMac20,2 (=0). - // Added logic checks provided model years `AppleModelYear` first year greater than or equal to 2020. - if ((info->modelIndex >= 0 && AppleModelYear[info->modelIndex][0] >= 2017 && info->decodedYear < 7) - || (info->decodedYear == 0 && info->model[0] >= 'H')) { - info->decodedYear += 2020; - } else if (info->decodedYear >= 0) { - info->decodedYear += 2010; - } else { - printf("WARN: Invalid year symbol '%c'!\n", info->year[0]); - info->valid = false; - } - - if (info->week[0] > '0' && info->week[0] <= '9') - info->decodedWeek = info->week[0] - '0'; - else - info->decodedWeek = alpha_to_value(info->week[0], AppleTblWeek, AppleWeekBlacklist); - if (info->decodedWeek > 0) { - if (info->decodedYear > 0) - info->decodedWeek += alpha_to_value(info->year[0], AppleTblWeekAdd, NULL); - } else { - printf("WARN: Invalid week symbol '%c'!\n", info->week[0]); - info->valid = false; - } + // These are not exactly year and week, lower year bit is used for week encoding. + info->year[0] = *serial++; + info->week[0] = *serial++; + + // New encoding started in 2010. + info->decodedYear = alpha_to_value(info->year[0], AppleTblYear, AppleYearBlacklist); + // Since year can be encoded ambiguously, check the model code for 2010/2020 difference. + // Old check relies on first letter of model to be greater than or equal to H, which breaks compatibility with iMac20,2 (=0). + // Added logic checks provided model years `AppleModelYear` first year greater than or equal to 2020. + if ((info->modelIndex >= 0 && AppleModelYear[info->modelIndex][0] >= 2017 && info->decodedYear < 7) + || (info->decodedYear == 0 && info->model[0] >= 'H')) { + info->decodedYear += 2020; + } else if (info->decodedYear >= 0) { + info->decodedYear += 2010; + } else { + printf("WARN: Invalid year symbol '%c'!\n", info->year[0]); + info->valid = false; + } + + if (info->week[0] > '0' && info->week[0] <= '9') + info->decodedWeek = info->week[0] - '0'; + else + info->decodedWeek = alpha_to_value(info->week[0], AppleTblWeek, AppleWeekBlacklist); + if (info->decodedWeek > 0) { + if (info->decodedYear > 0) + info->decodedWeek += alpha_to_value(info->year[0], AppleTblWeekAdd, NULL); + } else { + printf("WARN: Invalid week symbol '%c'!\n", info->week[0]); + info->valid = false; + } } else { - info->year[0] = *serial++; - info->week[0] = *serial++; - info->week[1] = *serial++; - - // This is proven by MacPro5,1 valid serials from 2011 and 2012. - if (info->year[0] >= '0' && info->year[0] <= '2') { - info->decodedYear = 2010 + info->year[0] - '0'; - } else if (info->year[0] >= '3' && info->year[0] <= '9') { - info->decodedYear = 2000 + info->year[0] - '0'; - } else { - info->decodedYear = -1; - printf("WARN: Invalid year symbol '%c'!\n", info->year[0]); - info->valid = false; - } - - for (int32_t i = 0; i < 2; i++) { - if (info->week[i] >= '0' && info->week[i] <= '9') { - info->decodedWeek += (i == 0 ? 10 : 1) * (info->week[i] - '0'); - } else { - info->decodedWeek = -1; - printf("WARN: Invalid week symbol '%c'!\n", info->week[i]); - info->valid = false; - break; - } - } + info->year[0] = *serial++; + info->week[0] = *serial++; + info->week[1] = *serial++; + + // This is proven by MacPro5,1 valid serials from 2011 and 2012. + if (info->year[0] >= '0' && info->year[0] <= '2') { + info->decodedYear = 2010 + info->year[0] - '0'; + } else if (info->year[0] >= '3' && info->year[0] <= '9') { + info->decodedYear = 2000 + info->year[0] - '0'; + } else { + info->decodedYear = -1; + printf("WARN: Invalid year symbol '%c'!\n", info->year[0]); + info->valid = false; + } + + for (int32_t i = 0; i < 2; i++) { + if (info->week[i] >= '0' && info->week[i] <= '9') { + info->decodedWeek += (i == 0 ? 10 : 1) * (info->week[i] - '0'); + } else { + info->decodedWeek = -1; + printf("WARN: Invalid week symbol '%c'!\n", info->week[i]); + info->valid = false; + break; + } + } } if (info->decodedWeek < SERIAL_WEEK_MIN || info->decodedWeek > SERIAL_WEEK_MAX) { - printf("WARN: Decoded week %d is out of valid range [%d, %d]!\n", info->decodedWeek, SERIAL_WEEK_MIN, SERIAL_WEEK_MAX); - info->decodedWeek = -1; + printf("WARN: Decoded week %d is out of valid range [%d, %d]!\n", info->decodedWeek, SERIAL_WEEK_MIN, SERIAL_WEEK_MAX); + info->decodedWeek = -1; } if (info->decodedYear > 0 && info->modelIndex >= 0) { - bool found = false; - for (size_t i = 0; !found && i < APPLE_MODEL_YEAR_MAX && AppleModelYear[info->modelIndex][i]; i++) - if ((int32_t)AppleModelYear[info->modelIndex][i] == info->decodedYear) - found = true; - if (!found) { - printf("WARN: Invalid year %d for model %s\n", info->decodedYear, ApplePlatformData[info->modelIndex].productName); - info->valid = false; - } + bool found = false; + for (size_t i = 0; !found && i < APPLE_MODEL_YEAR_MAX && AppleModelYear[info->modelIndex][i]; i++) + if ((int32_t)AppleModelYear[info->modelIndex][i] == info->decodedYear) + found = true; + if (!found) { + printf("WARN: Invalid year %d for model %s\n", info->decodedYear, ApplePlatformData[info->modelIndex].productName); + info->valid = false; + } } // Decode production line and copy int32_t mul[] = {68, 34, 1}; for (uint32_t i = 0; i < ARRAY_SIZE(mul); i++) { - info->line[i] = *serial++; - int32_t tmp = base34_to_value(info->line[i], mul[i]); - if (tmp >= 0) { - info->decodedLine += tmp; - } else { - printf("WARN: Invalid line symbol '%c'!\n", info->line[i]); - info->valid = false; - break; - } + info->line[i] = *serial++; + int32_t tmp = base34_to_value(info->line[i], mul[i]); + if (tmp >= 0) { + info->decodedLine += tmp; + } else { + printf("WARN: Invalid line symbol '%c'!\n", info->line[i]); + info->valid = false; + break; + } } if (info->decodedLine >= 0) - info->decodedCopy = base34_to_value(info->line[0], 1) - line_to_rmin(info->decodedLine); + info->decodedCopy = base34_to_value(info->line[0], 1) - line_to_rmin(info->decodedLine); if (print) { - printf("%14s: %4s - ", "Country", info->country); - if (info->legacyCountryIdx >= 0) - printf("%s\n", AppleLegacyLocationNames[info->legacyCountryIdx]); - else if (info->modernCountryIdx >= 0) - printf("%s\n", AppleLocationNames[info->modernCountryIdx]); - else - puts("Unknown, please report!"); - printf("%14s: %4s - %d\n", "Year", info->year, info->decodedYear); - printf("%14s: %4s - %d", "Week", info->week, info->decodedWeek); - if (info->decodedYear > 0 && info->decodedWeek > 0) { - struct tm startd = { - .tm_isdst = -1, - .tm_year = info->decodedYear - 1900, - .tm_mday = 1 + 7 * (info->decodedWeek-1), - .tm_mon = 0 - }; - if (mktime(&startd) >= 0) { - printf(" (%02d.%02d.%04d", startd.tm_mday, startd.tm_mon+1, startd.tm_year+1900); - if (info->decodedWeek == 53 && startd.tm_mday != 31) { - printf("-31.12.%04d", startd.tm_year+1900); - } else if (info->decodedWeek < 53) { - startd.tm_mday += 6; - if (mktime(&startd)) - printf("-%02d.%02d.%04d", startd.tm_mday, startd.tm_mon+1, startd.tm_year+1900); - } - puts(")"); - } - } else { - puts(""); - } - printf("%14s: %4s - %d (copy %d)\n", "Line", info->line, info->decodedLine, - info->decodedCopy >= 0 ? info->decodedCopy + 1 : -1); - printf("%14s: %4s - %s\n", "Model", info->model, info->modelIndex >= 0 ? - ApplePlatformData[info->modelIndex].productName : "Unknown"); - printf("%14s: %s\n", "SystemModel", info->appleModel != NULL ? info->appleModel : "Unknown, please report!"); - printf("%14s: %s\n", "Valid", info->valid ? "Possibly" : "Unlikely"); + printf("%14s: %4s - ", "Country", info->country); + if (info->legacyCountryIdx >= 0) + printf("%s\n", AppleLegacyLocationNames[info->legacyCountryIdx]); + else if (info->modernCountryIdx >= 0) + printf("%s\n", AppleLocationNames[info->modernCountryIdx]); + else + puts("Unknown, please report!"); + printf("%14s: %4s - %d\n", "Year", info->year, info->decodedYear); + printf("%14s: %4s - %d", "Week", info->week, info->decodedWeek); + if (info->decodedYear > 0 && info->decodedWeek > 0) { + struct tm startd = { + .tm_isdst = -1, + .tm_year = info->decodedYear - 1900, + .tm_mday = 1 + 7 * (info->decodedWeek-1), + .tm_mon = 0 + }; + if (mktime(&startd) >= 0) { + printf(" (%02d.%02d.%04d", startd.tm_mday, startd.tm_mon+1, startd.tm_year+1900); + if (info->decodedWeek == 53 && startd.tm_mday != 31) { + printf("-31.12.%04d", startd.tm_year+1900); + } else if (info->decodedWeek < 53) { + startd.tm_mday += 6; + if (mktime(&startd)) + printf("-%02d.%02d.%04d", startd.tm_mday, startd.tm_mon+1, startd.tm_year+1900); + } + puts(")"); + } + } else { + puts(""); + } + printf("%14s: %4s - %d (copy %d)\n", "Line", info->line, info->decodedLine, + info->decodedCopy >= 0 ? info->decodedCopy + 1 : -1); + printf("%14s: %4s - %s\n", "Model", info->model, info->modelIndex >= 0 ? + ApplePlatformData[info->modelIndex].productName : "Unknown"); + printf("%14s: %s\n", "SystemModel", info->appleModel != NULL ? info->appleModel : "Unknown, please report!"); + printf("%14s: %s\n", "Valid", info->valid ? "Possibly" : "Unlikely"); } return true; @@ -481,74 +425,74 @@ bool get_serial_info(const char *serial, SERIALINFO *info, bool print) { bool get_serial(SERIALINFO *info) { if (info->modelIndex < 0 && info->model[0] == '\0') { - printf("ERROR: Unable to determine model!\n"); - return false; + printf("ERROR: Unable to determine model!\n"); + return false; } if (info->model[0] == '\0') { - strncpy(info->model, get_model_code((AppleModel)info->modelIndex, false), MODEL_CODE_NEW_LEN); - info->model[MODEL_CODE_NEW_LEN] = '\0'; + strncpy(info->model, get_model_code((AppleModel)info->modelIndex, false), MODEL_CODE_NEW_LEN); + info->model[MODEL_CODE_NEW_LEN] = '\0'; } size_t country_len = strlen(info->country); if (country_len == 0) { - // Random country choice strongly decreases key verification probability. - country_len = strlen(info->model) == MODEL_CODE_NEW_LEN ? COUNTRY_NEW_LEN : COUNTRY_OLD_LEN; - if (info->modelIndex < 0) { - strncpy(info->country, country_len == COUNTRY_OLD_LEN ? AppleLegacyLocations[0] : AppleLocations[0], COUNTRY_NEW_LEN+1); - } else { - strncpy(info->country, &ApplePlatformData[info->modelIndex].serialNumber[0], country_len); - info->country[country_len] = '\0'; - } + // Random country choice strongly decreases key verification probability. + country_len = strlen(info->model) == MODEL_CODE_NEW_LEN ? COUNTRY_NEW_LEN : COUNTRY_OLD_LEN; + if (info->modelIndex < 0) { + strncpy(info->country, country_len == COUNTRY_OLD_LEN ? AppleLegacyLocations[0] : AppleLocations[0], COUNTRY_NEW_LEN+1); + } else { + strncpy(info->country, &ApplePlatformData[info->modelIndex].serialNumber[0], country_len); + info->country[country_len] = '\0'; + } } if (info->decodedYear < 0) { - if (info->modelIndex < 0) - info->decodedYear = country_len == COUNTRY_OLD_LEN ? SERIAL_YEAR_OLD_MAX : SERIAL_YEAR_NEW_MID; - else - info->decodedYear = (int32_t)get_production_year((AppleModel)info->modelIndex, false); + if (info->modelIndex < 0) + info->decodedYear = country_len == COUNTRY_OLD_LEN ? SERIAL_YEAR_OLD_MAX : SERIAL_YEAR_NEW_MID; + else + info->decodedYear = (int32_t)get_production_year((AppleModel)info->modelIndex, false); } // Last week is too rare to care if (info->decodedWeek < 0) - info->decodedWeek = (int32_t)pseudo_random_between(SERIAL_WEEK_MIN, SERIAL_WEEK_MAX-1); + info->decodedWeek = (int32_t)pseudo_random_between(SERIAL_WEEK_MIN, SERIAL_WEEK_MAX-1); if (country_len == COUNTRY_OLD_LEN) { - if (info->decodedYear < SERIAL_YEAR_OLD_MIN || info->decodedYear > SERIAL_YEAR_OLD_MAX) { - printf("ERROR: Year %d is out of valid legacy range [%d, %d]!\n", info->decodedYear, SERIAL_YEAR_OLD_MIN, SERIAL_YEAR_OLD_MAX); - return false; - } - - info->year[0] = '0' + (char)((info->decodedYear - 2000) % 10); - info->week[0] = '0' + (char)((info->decodedWeek) / 10); - info->week[1] = '0' + (info->decodedWeek) % 10; + if (info->decodedYear < SERIAL_YEAR_OLD_MIN || info->decodedYear > SERIAL_YEAR_OLD_MAX) { + printf("ERROR: Year %d is out of valid legacy range [%d, %d]!\n", info->decodedYear, SERIAL_YEAR_OLD_MIN, SERIAL_YEAR_OLD_MAX); + return false; + } + + info->year[0] = '0' + (char)((info->decodedYear - 2000) % 10); + info->week[0] = '0' + (char)((info->decodedWeek) / 10); + info->week[1] = '0' + (info->decodedWeek) % 10; } else { - if (info->decodedYear < SERIAL_YEAR_NEW_MIN || info->decodedYear > SERIAL_YEAR_NEW_MAX) { - printf("ERROR: Year %d is out of valid modern range [%d, %d]!\n", info->decodedYear, SERIAL_YEAR_NEW_MIN, SERIAL_YEAR_NEW_MAX); - return false; - } + if (info->decodedYear < SERIAL_YEAR_NEW_MIN || info->decodedYear > SERIAL_YEAR_NEW_MAX) { + printf("ERROR: Year %d is out of valid modern range [%d, %d]!\n", info->decodedYear, SERIAL_YEAR_NEW_MIN, SERIAL_YEAR_NEW_MAX); + return false; + } - size_t base_new_year = 2010; - if (info->decodedYear >= SERIAL_YEAR_NEW_MID) { - base_new_year = 2020; - } + size_t base_new_year = 2010; + if (info->decodedYear >= SERIAL_YEAR_NEW_MID) { + base_new_year = 2020; + } - info->year[0] = AppleYearReverse[(info->decodedYear - base_new_year) * 2 + (info->decodedWeek >= 27)]; - info->week[0] = AppleWeekReverse[info->decodedWeek]; + info->year[0] = AppleYearReverse[(info->decodedYear - base_new_year) * 2 + (info->decodedWeek >= 27)]; + info->week[0] = AppleWeekReverse[info->decodedWeek]; } if (info->decodedLine < 0) - info->decodedLine = (int32_t)pseudo_random_between(SERIAL_LINE_MIN, SERIAL_LINE_MAX); + info->decodedLine = (int32_t)pseudo_random_between(SERIAL_LINE_MIN, SERIAL_LINE_MAX); int32_t rmin = line_to_rmin(info->decodedLine); // Verify and apply user supplied copy if any if (info->decodedCopy >= 0) { - rmin += info->decodedCopy - 1; - if (rmin * 68 > info->decodedLine) { - printf("ERROR: Copy %d cannot represent line %d!\n", info->decodedCopy, info->decodedLine); - return false; - } + rmin += info->decodedCopy - 1; + if (rmin * 68 > info->decodedLine) { + printf("ERROR: Copy %d cannot represent line %d!\n", info->decodedCopy, info->decodedLine); + return false; + } } info->line[0] = AppleBase34Reverse[rmin]; @@ -561,87 +505,87 @@ bool get_serial(SERIALINFO *info) { void get_mlb(SERIALINFO *info, char *dst, size_t sz) { // This is a direct reverse from CCC, rework it later... if (info->modelIndex < 0) { - printf("WARN: Unknown model, assuming default!\n"); - info->modelIndex = APPLE_MODEL_MAX - 1; + printf("WARN: Unknown model, assuming default!\n"); + info->modelIndex = APPLE_MODEL_MAX - 1; } do { - uint32_t year = 0, week = 0; - - bool legacy = strlen(info->country) == COUNTRY_OLD_LEN; - - if (legacy) { - year = (uint32_t)(info->year[0] - '0'); - week = (uint32_t)(info->week[0] - '0') * 10 + (uint32_t)(info->week[1] - '0'); - } else { - char syear = info->year[0]; - char sweek = info->week[0]; - - const char srcyear[] = "CDFGHJKLMNPQRSTVWXYZ"; - const char dstyear[] = "00112233445566778899"; - for (size_t i = 0; i < ARRAY_SIZE(srcyear)-1; i++) { - if (syear == srcyear[i]) { - year = (uint32_t)(dstyear[i] - '0'); - break; - } - } - - const char overrides[] = "DGJLNQSVXZ"; - for (size_t i = 0; i < ARRAY_SIZE(overrides)-1; i++) { - if (syear == overrides[i]) { - week = 27; - break; - } - } - - const char srcweek[] = "123456789CDFGHJKLMNPQRSTVWXYZ"; - for (size_t i = 0; i < ARRAY_SIZE(srcweek)-1; i++) { - if (sweek == srcweek[i]) { - week += i + 1; - break; - } - } - - // This is silently not handled, and it should not be needed for normal serials. - // Bugged MacBookPro6,2 and MacBookPro7,1 will gladly hit it. - if (week < SERIAL_WEEK_MIN) { - snprintf(dst, sz, "FAIL-ZERO-%c", sweek); - return; - } - } - - week--; - - if (week <= 9) { - if (week == 0) { - week = SERIAL_WEEK_MAX; - if (year == 0) - year = 9; - else - year--; - } - } - - if (legacy) { - char code[4] = {0}; - // The loop is not present in CCC, but it throws an exception here, - // and effectively generates nothing. The logic is crazy :/. - // Also, it was likely meant to be written as pseudo_random() % 0x8000. - while (!get_ascii7(pseudo_random_between(0, 0x7FFE) * 0x73BA1C, code, sizeof(code))); - const char *board = get_board_code(info->modelIndex, false); - char suffix = AppleBase34Reverse[pseudo_random() % 34]; - snprintf(dst, sz, "%s%d%02d0%s%s%c", info->country, year, week, code, board, suffix); - } else { - const char *part1 = MLBBlock1[pseudo_random() % ARRAY_SIZE(MLBBlock1)]; - const char *part2 = MLBBlock2[pseudo_random() % ARRAY_SIZE(MLBBlock2)]; - const char *board = get_board_code(info->modelIndex, false); - const char *part3 = MLBBlock3[pseudo_random() % ARRAY_SIZE(MLBBlock3)]; - - snprintf(dst, sz, "%s%d%02d%s%s%s%s", info->country, year, week, part1, part2, board, part3); - } + uint32_t year = 0, week = 0; + + bool legacy = strlen(info->country) == COUNTRY_OLD_LEN; + + if (legacy) { + year = (uint32_t)(info->year[0] - '0'); + week = (uint32_t)(info->week[0] - '0') * 10 + (uint32_t)(info->week[1] - '0'); + } else { + char syear = info->year[0]; + char sweek = info->week[0]; + + const char srcyear[] = "CDFGHJKLMNPQRSTVWXYZ"; + const char dstyear[] = "00112233445566778899"; + for (size_t i = 0; i < ARRAY_SIZE(srcyear)-1; i++) { + if (syear == srcyear[i]) { + year = (uint32_t)(dstyear[i] - '0'); + break; + } + } + + const char overrides[] = "DGJLNQSVXZ"; + for (size_t i = 0; i < ARRAY_SIZE(overrides)-1; i++) { + if (syear == overrides[i]) { + week = 27; + break; + } + } + + const char srcweek[] = "123456789CDFGHJKLMNPQRSTVWXYZ"; + for (size_t i = 0; i < ARRAY_SIZE(srcweek)-1; i++) { + if (sweek == srcweek[i]) { + week += i + 1; + break; + } + } + + // This is silently not handled, and it should not be needed for normal serials. + // Bugged MacBookPro6,2 and MacBookPro7,1 will gladly hit it. + if (week < SERIAL_WEEK_MIN) { + snprintf(dst, sz, "FAIL-ZERO-%c", sweek); + return; + } + } + + week--; + + if (week <= 9) { + if (week == 0) { + week = SERIAL_WEEK_MAX; + if (year == 0) + year = 9; + else + year--; + } + } + + if (legacy) { + char code[4] = {0}; + // The loop is not present in CCC, but it throws an exception here, + // and effectively generates nothing. The logic is crazy :/. + // Also, it was likely meant to be written as pseudo_random() % 0x8000. + while (!get_ascii7(pseudo_random_between(0, 0x7FFE) * 0x73BA1C, code, sizeof(code))); + const char *board = get_board_code(info->modelIndex, false); + char suffix = AppleBase34Reverse[pseudo_random() % 34]; + snprintf(dst, sz, "%s%d%02d0%s%s%c", info->country, year, week, code, board, suffix); + } else { + const char *part1 = MLBBlock1[pseudo_random() % ARRAY_SIZE(MLBBlock1)]; + const char *part2 = MLBBlock2[pseudo_random() % ARRAY_SIZE(MLBBlock2)]; + const char *board = get_board_code(info->modelIndex, false); + const char *part3 = MLBBlock3[pseudo_random() % ARRAY_SIZE(MLBBlock3)]; + + snprintf(dst, sz, "%s%d%02d%s%s%s%s", info->country, year, week, part1, part2, board, part3); + } } while (!verify_mlb_checksum(dst, strlen(dst))); } -static void get_system_info(void) { +void get_system_info(void) { #ifdef __APPLE__ CFDataRef model = get_ioreg_entry("IODeviceTree:/", CFSTR("model"), CFDataGetTypeID()); CFDataRef board = get_ioreg_entry("IODeviceTree:/", CFSTR("board-id"), CFDataGetTypeID()); @@ -654,82 +598,82 @@ static void get_system_info(void) { CFDataRef pwr[5] = {0}; CFStringRef pwrname[5] = { - CFSTR("Gq3489ugfi"), - CFSTR("Fyp98tpgj"), - CFSTR("kbjfrfpoJU"), - CFSTR("oycqAZloTNDm"), - CFSTR("abKPld1EcMni"), + CFSTR("Gq3489ugfi"), + CFSTR("Fyp98tpgj"), + CFSTR("kbjfrfpoJU"), + CFSTR("oycqAZloTNDm"), + CFSTR("abKPld1EcMni"), }; for (size_t i = 0; i < ARRAY_SIZE(pwr); i++) - pwr[i] = get_ioreg_entry("IOPower:/", pwrname[i], CFDataGetTypeID()); + pwr[i] = get_ioreg_entry("IOPower:/", pwrname[i], CFDataGetTypeID()); if (model) { - printf("%14s: %.*s\n", "Model", (int)CFDataGetLength(model), CFDataGetBytePtr(model)); - CFRelease(model); + printf("%14s: %.*s\n", "Model", (int)CFDataGetLength(model), CFDataGetBytePtr(model)); + CFRelease(model); } if (board) { - printf("%14s: %.*s\n", "Board ID", (int)CFDataGetLength(board), CFDataGetBytePtr(board)); - CFRelease(board); + printf("%14s: %.*s\n", "Board ID", (int)CFDataGetLength(board), CFDataGetBytePtr(board)); + CFRelease(board); } if (efiver) { - printf("%14s: %.*s\n", "FW Version", (int)CFDataGetLength(efiver), CFDataGetBytePtr(efiver)); - CFRelease(efiver); + printf("%14s: %.*s\n", "FW Version", (int)CFDataGetLength(efiver), CFDataGetBytePtr(efiver)); + CFRelease(efiver); } if (hwuuid) { - printf("%14s: %s\n", "Hardware UUID", CFStringGetCStringPtr(hwuuid, kCFStringEncodingMacRoman)); - CFRelease(hwuuid); + printf("%14s: %s\n", "Hardware UUID", CFStringGetCStringPtr(hwuuid, kCFStringEncodingMacRoman)); + CFRelease(hwuuid); } puts(""); if (serial) { - const char *cstr = CFStringGetCStringPtr(serial, kCFStringEncodingMacRoman); - printf("%14s: %s\n", "Serial Number", cstr); - SERIALINFO info; - get_serial_info(cstr, &info, true); - CFRelease(serial); - puts(""); + const char *cstr = CFStringGetCStringPtr(serial, kCFStringEncodingMacRoman); + printf("%14s: %s\n", "Serial Number", cstr); + SERIALINFO info; + get_serial_info(cstr, &info, true); + CFRelease(serial); + puts(""); } if (smuuid) { - if (CFDataGetLength(smuuid) == SZUUID) { - const uint8_t *p = CFDataGetBytePtr(smuuid); - printf("%14s: " PRIUUID "\n", "System ID", CASTUUID(p)); - } - CFRelease(smuuid); + if (CFDataGetLength(smuuid) == SZUUID) { + const uint8_t *p = CFDataGetBytePtr(smuuid); + printf("%14s: " PRIUUID "\n", "System ID", CASTUUID(p)); + } + CFRelease(smuuid); } if (rom) { - if (CFDataGetLength(rom) == 6) { - const uint8_t *p = CFDataGetBytePtr(rom); - printf("%14s: %02X%02X%02X%02X%02X%02X\n", "ROM", p[0], p[1], p[2], p[3], p[4], p[5]); - } - CFRelease(rom); + if (CFDataGetLength(rom) == 6) { + const uint8_t *p = CFDataGetBytePtr(rom); + printf("%14s: %02X%02X%02X%02X%02X%02X\n", "ROM", p[0], p[1], p[2], p[3], p[4], p[5]); + } + CFRelease(rom); } if (mlb) { - printf("%14s: %.*s\n", "MLB", (int)CFDataGetLength(mlb), CFDataGetBytePtr(mlb)); - if (!verify_mlb_checksum((const char *)CFDataGetBytePtr(mlb), CFDataGetLength(mlb))) - printf("WARN: Invalid MLB checksum!\n"); - CFRelease(mlb); + printf("%14s: %.*s\n", "MLB", (int)CFDataGetLength(mlb), CFDataGetBytePtr(mlb)); + if (!verify_mlb_checksum((const char *)CFDataGetBytePtr(mlb), CFDataGetLength(mlb))) + printf("WARN: Invalid MLB checksum!\n"); + CFRelease(mlb); } puts(""); for (size_t i = 0; i < ARRAY_SIZE(pwr); i++) { - if (pwr[i]) { - printf("%14s: ", CFStringGetCStringPtr(pwrname[i], kCFStringEncodingMacRoman)); - const uint8_t *p = CFDataGetBytePtr(pwr[i]); - CFIndex sz = CFDataGetLength(pwr[i]); - for (CFIndex j = 0; j < sz; j++) - printf("%02X", p[j]); - puts(""); - CFRelease(pwr[i]); - } + if (pwr[i]) { + printf("%14s: ", CFStringGetCStringPtr(pwrname[i], kCFStringEncodingMacRoman)); + const uint8_t *p = CFDataGetBytePtr(pwr[i]); + CFIndex sz = CFDataGetLength(pwr[i]); + for (CFIndex j = 0; j < sz; j++) + printf("%02X", p[j]); + puts(""); + CFRelease(pwr[i]); + } } puts(""); @@ -738,29 +682,29 @@ static void get_system_info(void) { printf("Version %s. Use -h argument to see usage options.\n", PROGRAM_VERSION); } -static int usage(const char *app) { +int usage(const char *app) { printf( - "%s arguments:\n" - " --help (-h) show this help\n" - " --version (-v) show program version\n" - " --deriv (-d) generate all derivative serials\n" - " --generate (-g) generate serial for current model\n" - " --generate-all (-a) generate serial for all models\n" - " --info (-i) decode serial information\n" - " --verify verify MLB checksum\n" - " --list (-l) list known mac models\n" - " --list-products (-lp) list known product codes\n" - " --mlb generate MLB based on serial\n" - " --sys (-s) get system info\n\n" - "Tuning options:\n" - " --model (-m) mac model used for generation\n" - " --num (-n) number of generated pairs\n" - " --year (-y) year used for generation\n" - " --week (-w) week used for generation\n" - " --country (-c) country location used for generation\n" - " --copy (-o) production copy index\n" - " --line (-e) production line\n" - " --platform (-p) platform code used for generation\n\n", app); + "%s arguments:\n" + " --help (-h) show this help\n" + " --version (-v) show program version\n" + " --deriv (-d) generate all derivative serials\n" + " --generate (-g) generate serial for current model\n" + " --generate-all (-a) generate serial for all models\n" + " --info (-i) decode serial information\n" + " --verify verify MLB checksum\n" + " --list (-l) list known mac models\n" + " --list-products (-lp) list known product codes\n" + " --mlb generate MLB based on serial\n" + " --sys (-s) get system info\n\n" + "Tuning options:\n" + " --model (-m) mac model used for generation\n" + " --num (-n) number of generated pairs\n" + " --year (-y) year used for generation\n" + " --week (-w) week used for generation\n" + " --country (-c) country location used for generation\n" + " --copy (-o) production copy index\n" + " --line (-e) production line\n" + " --platform (-p) platform code used for generation\n\n", app); return EXIT_FAILURE; } @@ -781,208 +725,208 @@ void strfcat(char *src, const char *fmt, ...) PROGRAMMODE mode = MODE_SYSTEM_INFO; const char *passed_serial = NULL; SERIALINFO info = { - .modelIndex = -1, - .decodedYear = -1, - .decodedWeek = -1, - .decodedCopy = -1, - .decodedLine = -1 + .modelIndex = -1, + .decodedYear = -1, + .decodedWeek = -1, + .decodedCopy = -1, + .decodedLine = -1 }; int32_t limit = 10; for (int i = 1; i < argc; i++) { - if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { - usage(argv[0]); - return EXIT_SUCCESS; - } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { - printf("ugrobator %s\n", PROGRAM_VERSION); - return EXIT_SUCCESS; - } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--generate")) { - mode = MODE_GENERATE_CURRENT; - } else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--generate-all")) { - mode = MODE_GENERATE_ALL; - } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--info")) { - if (++i == argc) return usage(argv[0]); - mode = MODE_SERIAL_INFO; - passed_serial = argv[i]; - } else if (!strcmp(argv[i], "--verify")) { - if (++i == argc) return usage(argv[0]); - mode = MODE_MLB_INFO; - passed_serial = argv[i]; - } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) { - mode = MODE_LIST_MODELS; - } else if (!strcmp(argv[i], "-lp") || !strcmp(argv[i], "--list-products")) { - mode = MODE_LIST_PRODUCTS; - } else if (!strcmp(argv[i], "-mlb") || !strcmp(argv[i], "--mlb")) { - // -mlb is supported due to legacy versions. - if (++i == argc) return usage(argv[0]); - mode = MODE_GENERATE_MLB; - passed_serial = argv[i]; - } else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--deriv")) { - if (++i == argc) return usage(argv[0]); - mode = MODE_GENERATE_DERIVATIVES; - passed_serial = argv[i]; - } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--sys")) { - mode = MODE_SYSTEM_INFO; - } else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--model")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - if (argv[i][0] >= '0' && argv[i][0] <= '9') { - info.modelIndex = atoi(argv[i]); - } else { - for (int32_t j = 0; j < APPLE_MODEL_MAX; j++) { - if (!strcmp(argv[i], ApplePlatformData[j].productName)) { - info.modelIndex = j; - break; - } - } - } - if (info.modelIndex < 0 || info.modelIndex > APPLE_MODEL_MAX) { - printf("Model id (%d) or name (%s) is out of valid range [0, %d]!\n", info.modelIndex, argv[i], APPLE_MODEL_MAX-1); - return EXIT_FAILURE; - } - } else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--num")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - limit = atoi(argv[i]); - if (limit <= 0) { - printf("Cannot generate %d pairs!\n", limit); - return EXIT_FAILURE; - } - } else if (!strcmp(argv[i], "-y") || !strcmp(argv[i], "--year")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - info.decodedYear = atoi(argv[i]); - if (info.decodedYear < SERIAL_YEAR_MIN || info.decodedYear > SERIAL_YEAR_MAX) { - printf("Year %d is out of valid range [%d, %d]!\n", info.decodedYear, SERIAL_YEAR_MIN, SERIAL_YEAR_MAX); - return EXIT_FAILURE; - } - } else if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--week")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - info.decodedWeek = atoi(argv[i]); - if (info.decodedWeek < SERIAL_WEEK_MIN || info.decodedWeek > SERIAL_WEEK_MAX) { - printf("Week %d is out of valid range [%d, %d]!\n", info.decodedWeek, SERIAL_WEEK_MIN, SERIAL_WEEK_MAX); - return EXIT_FAILURE; - } - } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--country")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - size_t len = strlen(argv[i]); - if (len != COUNTRY_OLD_LEN && len != COUNTRY_NEW_LEN) { - printf("Country location %s is neither %d nor %d symbols long!\n", argv[i], COUNTRY_OLD_LEN, COUNTRY_NEW_LEN); - return EXIT_FAILURE; - } - strncpy(info.country, argv[i], COUNTRY_NEW_LEN+1); - } else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--platform")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - size_t len = strlen(argv[i]); - if (len != MODEL_CODE_OLD_LEN && len != MODEL_CODE_NEW_LEN) { - printf("Platform code %s is neither %d nor %d symbols long!\n", argv[i], MODEL_CODE_OLD_LEN, MODEL_CODE_NEW_LEN); - return EXIT_FAILURE; - } - strncpy(info.model, argv[i], MODEL_CODE_NEW_LEN+1); - } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--copy")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - info.decodedCopy = atoi(argv[i]); - if (info.decodedCopy < SERIAL_COPY_MIN || info.decodedCopy > SERIAL_COPY_MAX) { - printf("Copy %d is out of valid range [%d, %d]!\n", info.decodedCopy, SERIAL_COPY_MIN, SERIAL_COPY_MAX); - return EXIT_FAILURE; - } - } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--line")) { - if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; - if (++i == argc) return usage(argv[0]); - info.decodedLine = atoi(argv[i]); - if (info.decodedLine < SERIAL_LINE_MIN || info.decodedLine > SERIAL_LINE_MAX) { - printf("Line %d is out of valid range [%d, %d]!\n", info.decodedLine, SERIAL_LINE_MIN, SERIAL_LINE_MAX); - return EXIT_FAILURE; - } - } + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + usage(argv[0]); + return EXIT_SUCCESS; + } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { + printf("ugrobator %s\n", PROGRAM_VERSION); + return EXIT_SUCCESS; + } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--generate")) { + mode = MODE_GENERATE_CURRENT; + } else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--generate-all")) { + mode = MODE_GENERATE_ALL; + } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--info")) { + if (++i == argc) return usage(argv[0]); + mode = MODE_SERIAL_INFO; + passed_serial = argv[i]; + } else if (!strcmp(argv[i], "--verify")) { + if (++i == argc) return usage(argv[0]); + mode = MODE_MLB_INFO; + passed_serial = argv[i]; + } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) { + mode = MODE_LIST_MODELS; + } else if (!strcmp(argv[i], "-lp") || !strcmp(argv[i], "--list-products")) { + mode = MODE_LIST_PRODUCTS; + } else if (!strcmp(argv[i], "-mlb") || !strcmp(argv[i], "--mlb")) { + // -mlb is supported due to legacy versions. + if (++i == argc) return usage(argv[0]); + mode = MODE_GENERATE_MLB; + passed_serial = argv[i]; + } else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--deriv")) { + if (++i == argc) return usage(argv[0]); + mode = MODE_GENERATE_DERIVATIVES; + passed_serial = argv[i]; + } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--sys")) { + mode = MODE_SYSTEM_INFO; + } else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--model")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + if (argv[i][0] >= '0' && argv[i][0] <= '9') { + info.modelIndex = atoi(argv[i]); + } else { + for (int32_t j = 0; j < APPLE_MODEL_MAX; j++) { + if (!strcmp(argv[i], ApplePlatformData[j].productName)) { + info.modelIndex = j; + break; + } + } + } + if (info.modelIndex < 0 || info.modelIndex > APPLE_MODEL_MAX) { + printf("Model id (%d) or name (%s) is out of valid range [0, %d]!\n", info.modelIndex, argv[i], APPLE_MODEL_MAX-1); + return EXIT_FAILURE; + } + } else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--num")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + limit = atoi(argv[i]); + if (limit <= 0) { + printf("Cannot generate %d pairs!\n", limit); + return EXIT_FAILURE; + } + } else if (!strcmp(argv[i], "-y") || !strcmp(argv[i], "--year")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + info.decodedYear = atoi(argv[i]); + if (info.decodedYear < SERIAL_YEAR_MIN || info.decodedYear > SERIAL_YEAR_MAX) { + printf("Year %d is out of valid range [%d, %d]!\n", info.decodedYear, SERIAL_YEAR_MIN, SERIAL_YEAR_MAX); + return EXIT_FAILURE; + } + } else if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--week")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + info.decodedWeek = atoi(argv[i]); + if (info.decodedWeek < SERIAL_WEEK_MIN || info.decodedWeek > SERIAL_WEEK_MAX) { + printf("Week %d is out of valid range [%d, %d]!\n", info.decodedWeek, SERIAL_WEEK_MIN, SERIAL_WEEK_MAX); + return EXIT_FAILURE; + } + } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--country")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + size_t len = strlen(argv[i]); + if (len != COUNTRY_OLD_LEN && len != COUNTRY_NEW_LEN) { + printf("Country location %s is neither %d nor %d symbols long!\n", argv[i], COUNTRY_OLD_LEN, COUNTRY_NEW_LEN); + return EXIT_FAILURE; + } + strncpy(info.country, argv[i], COUNTRY_NEW_LEN+1); + } else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--platform")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + size_t len = strlen(argv[i]); + if (len != MODEL_CODE_OLD_LEN && len != MODEL_CODE_NEW_LEN) { + printf("Platform code %s is neither %d nor %d symbols long!\n", argv[i], MODEL_CODE_OLD_LEN, MODEL_CODE_NEW_LEN); + return EXIT_FAILURE; + } + strncpy(info.model, argv[i], MODEL_CODE_NEW_LEN+1); + } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--copy")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + info.decodedCopy = atoi(argv[i]); + if (info.decodedCopy < SERIAL_COPY_MIN || info.decodedCopy > SERIAL_COPY_MAX) { + printf("Copy %d is out of valid range [%d, %d]!\n", info.decodedCopy, SERIAL_COPY_MIN, SERIAL_COPY_MAX); + return EXIT_FAILURE; + } + } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--line")) { + if (mode == MODE_SYSTEM_INFO) mode = MODE_GENERATE_CURRENT; + if (++i == argc) return usage(argv[0]); + info.decodedLine = atoi(argv[i]); + if (info.decodedLine < SERIAL_LINE_MIN || info.decodedLine > SERIAL_LINE_MAX) { + printf("Line %d is out of valid range [%d, %d]!\n", info.decodedLine, SERIAL_LINE_MIN, SERIAL_LINE_MAX); + return EXIT_FAILURE; + } + } } if (mode == MODE_SYSTEM_INFO) { - get_system_info(); + get_system_info(); } else if (mode == MODE_SERIAL_INFO) { - get_serial_info(passed_serial, &info, true); + get_serial_info(passed_serial, &info, true); } else if (mode == MODE_MLB_INFO) { - size_t len = strlen(passed_serial); - if (len == 13 || len == 17) { - printf("Valid MLB length: %s\n", len == 13 ? "legacy" : "modern"); - } else { - printf("WARN: Invalid MLB length: %u\n", (unsigned) len); - } - if (verify_mlb_checksum(passed_serial, strlen(passed_serial))) { - printf("Valid MLB checksum.\n"); - } else { - printf("WARN: Invalid MLB checksum!\n"); - } + size_t len = strlen(passed_serial); + if (len == 13 || len == 17) { + printf("Valid MLB length: %s\n", len == 13 ? "legacy" : "modern"); + } else { + printf("WARN: Invalid MLB length: %u\n", (unsigned) len); + } + if (verify_mlb_checksum(passed_serial, strlen(passed_serial))) { + printf("Valid MLB checksum.\n"); + } else { + printf("WARN: Invalid MLB checksum!\n"); + } } else if (mode == MODE_LIST_MODELS) { - printf("Available models:\n"); - for (int32_t j = 0; j < APPLE_MODEL_MAX; j++) { - printf("%14s: %s\n", "Model", ApplePlatformData[j].productName); - printf("%14s: ", "Prod years"); - get_production_year((AppleModel)j, true); - printf("%14s: %s\n", "Base Serial", ApplePlatformData[j].serialNumber); - printf("%14s: ", "Model codes"); - get_model_code((AppleModel)j, true); - printf("%14s: ", "Board codes"); - get_board_code((AppleModel)j, true); - puts(""); - } - printf("Available legacy location codes:\n"); - for (size_t j = 0; j < ARRAY_SIZE(AppleLegacyLocations); j++) - printf(" - %s, %s\n", AppleLegacyLocations[j], AppleLegacyLocationNames[j]); - printf("\nAvailable new location codes:\n"); - for (size_t j = 0; j < ARRAY_SIZE(AppleLocations); j++) - printf(" - %s, %s\n", AppleLocations[j], AppleLocationNames[j]); - puts(""); + printf("Available models:\n"); + for (int32_t j = 0; j < APPLE_MODEL_MAX; j++) { + printf("%14s: %s\n", "Model", ApplePlatformData[j].productName); + printf("%14s: ", "Prod years"); + get_production_year((AppleModel)j, true); + printf("%14s: %s\n", "Base Serial", ApplePlatformData[j].serialNumber); + printf("%14s: ", "Model codes"); + get_model_code((AppleModel)j, true); + printf("%14s: ", "Board codes"); + get_board_code((AppleModel)j, true); + puts(""); + } + printf("Available legacy location codes:\n"); + for (size_t j = 0; j < ARRAY_SIZE(AppleLegacyLocations); j++) + printf(" - %s, %s\n", AppleLegacyLocations[j], AppleLegacyLocationNames[j]); + printf("\nAvailable new location codes:\n"); + for (size_t j = 0; j < ARRAY_SIZE(AppleLocations); j++) + printf(" - %s, %s\n", AppleLocations[j], AppleLocationNames[j]); + puts(""); } else if (mode == MODE_LIST_PRODUCTS) { - for (size_t j = 0; j < ARRAY_SIZE(AppleModelDesc); j++) - printf("%4s - %s\n", AppleModelDesc[j].code, AppleModelDesc[j].name); + for (size_t j = 0; j < ARRAY_SIZE(AppleModelDesc); j++) + printf("%4s - %s\n", AppleModelDesc[j].code, AppleModelDesc[j].name); } else if (mode == MODE_GENERATE_MLB) { - if (get_serial_info(passed_serial, &info, false)) { - char mlb[MLB_MAX_SIZE]; - get_mlb(&info, mlb, MLB_MAX_SIZE); - printf("%s\n", mlb); - } + if (get_serial_info(passed_serial, &info, false)) { + char mlb[MLB_MAX_SIZE]; + get_mlb(&info, mlb, MLB_MAX_SIZE); + printf("%s\n", mlb); + } } else if (mode == MODE_GENERATE_CURRENT) { - if (info.modelIndex < 0) - info.modelIndex = get_current_model(); - for (int32_t i = 0; i < limit; i++) { - SERIALINFO tmp = info; - if (get_serial(&tmp)) { - char mlb[MLB_MAX_SIZE]; - get_mlb(&tmp, mlb, MLB_MAX_SIZE); - printf("%s%s%s%s%s | %s\n", tmp.country, tmp.year, tmp.week, tmp.line, tmp.model, mlb); - } - } + if (info.modelIndex < 0) + info.modelIndex = get_current_model(); + for (int32_t i = 0; i < limit; i++) { + SERIALINFO tmp = info; + if (get_serial(&tmp)) { + char mlb[MLB_MAX_SIZE]; + get_mlb(&tmp, mlb, MLB_MAX_SIZE); + printf("%s%s%s%s%s | %s\n", tmp.country, tmp.year, tmp.week, tmp.line, tmp.model, mlb); + } + } } else if (mode == MODE_GENERATE_ALL) { - for (int32_t i = 0; i < APPLE_MODEL_MAX; i++) { - info.modelIndex = i; - for (int32_t j = 0; j < limit; j++) { - SERIALINFO tmp = info; - if (get_serial(&tmp)) { - char mlb[MLB_MAX_SIZE]; - get_mlb(&tmp, mlb, MLB_MAX_SIZE); - printf("%14s | %s%s%s%s%s | %s\n", ApplePlatformData[info.modelIndex].productName, - tmp.country, tmp.year, tmp.week, tmp.line, tmp.model, mlb); - } - } - } + for (int32_t i = 0; i < APPLE_MODEL_MAX; i++) { + info.modelIndex = i; + for (int32_t j = 0; j < limit; j++) { + SERIALINFO tmp = info; + if (get_serial(&tmp)) { + char mlb[MLB_MAX_SIZE]; + get_mlb(&tmp, mlb, MLB_MAX_SIZE); + printf("%14s | %s%s%s%s%s | %s\n", ApplePlatformData[info.modelIndex].productName, + tmp.country, tmp.year, tmp.week, tmp.line, tmp.model, mlb); + } + } + } } else if (mode == MODE_GENERATE_DERIVATIVES) { - if (get_serial_info(passed_serial, &info, false)) { - int rmin = line_to_rmin(info.decodedLine); - for (int32_t k = 0; k < 34; k++) { - int32_t start = k * 68; - if (info.decodedLine > start && info.decodedLine - start <= SERIAL_LINE_REPR_MAX) { - int32_t rem = info.decodedLine - start; - printf("%s%s%s%c%c%c%s - copy %d\n", info.country, info.year, info.week, AppleBase34Reverse[k], - AppleBase34Reverse[rem / 34], AppleBase34Reverse[rem % 34], info.model, k - rmin + 1); - } - } - } else { - return EXIT_FAILURE; - } + if (get_serial_info(passed_serial, &info, false)) { + int rmin = line_to_rmin(info.decodedLine); + for (int32_t k = 0; k < 34; k++) { + int32_t start = k * 68; + if (info.decodedLine > start && info.decodedLine - start <= SERIAL_LINE_REPR_MAX) { + int32_t rem = info.decodedLine - start; + printf("%s%s%s%c%c%c%s - copy %d\n", info.country, info.year, info.week, AppleBase34Reverse[k], + AppleBase34Reverse[rem / 34], AppleBase34Reverse[rem % 34], info.model, k - rmin + 1); + } + } + } else { + return EXIT_FAILURE; + } } } */ diff --git a/MacSerial/macserial.h b/MacSerial/macserial.h index 5dbc30ac..b55cc141 100644 --- a/MacSerial/macserial.h +++ b/MacSerial/macserial.h @@ -11,12 +11,7 @@ #include #include -#define PROGRAM_VERSION "2.1.7" - -#ifdef __GNUC__ -uint32_t arc4random(void) __attribute__((weak)); -uint32_t arc4random_uniform(uint32_t upper_bound) __attribute__((weak)); -#endif +#define PROGRAM_VERSION "2.1.8" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) diff --git a/MacSerial/modelinfo_autogen.h b/MacSerial/modelinfo_autogen.h index 41f98c5a..37e717bf 100755 --- a/MacSerial/modelinfo_autogen.h +++ b/MacSerial/modelinfo_autogen.h @@ -429,7 +429,7 @@ static const char *AppleBoardCode[][APPLE_BOARD_CODE_MAX] = { /* MacBookPro15,3 */ {"0000"}, /* MacBookPro15,4 */ {"0000"}, /* MacBookPro16,1 */ {"N9PR"}, - /* MacBookPro16,2 */ {"0000"}, + /* MacBookPro16,2 */ {"P8PG"}, /* MacBookPro16,3 */ {"0000"}, /* MacBookPro16,4 */ {"0000"}, /* MacBookPro2,1 */ {"000"}, @@ -472,7 +472,7 @@ static const char *AppleBoardCode[][APPLE_BOARD_CODE_MAX] = { /* Xserve3,1 */ {"63C", "1PH"}, /* iMac10,1 */ {"000"}, /* iMac11,1 */ {"000"}, - /* iMac11,2 */ {"000"}, + /* iMac11,2 */ {"DCJN"}, /* iMac11,3 */ {"000"}, /* iMac12,1 */ {"DJWK", "DM66", "DNJK", "DP0H", "DKG1", "DM65", "DNJJ", "DKG2", "DM67", "DNJL", "DP0K", "DP00"}, /* iMac12,2 */ {"DJWM", "DMT3", "DMT5", "DJWN", "DM69", "DJWP", "DM6C"}, @@ -9765,6 +9765,33 @@ static APPLE_MODEL_DESC AppleModelDesc[] = { {"Q6LW", "MacBook Air (M1, 2020)"}, {"Q6LX", "MacBook Air (M1, 2020)"}, {"Q6LY", "MacBook Air (M1, 2020)"}, + {"Q6X0", "iMac (24-inch, M1, 2021)"}, + {"Q6X2", "iMac (24-inch, M1, 2021)"}, + {"Q6X3", "iMac (24-inch, M1, 2021)"}, + {"Q6X4", "iMac (24-inch, M1, 2021)"}, + {"Q6X5", "iMac (24-inch, M1, 2021)"}, + {"Q6X6", "iMac (24-inch, M1, 2021)"}, + {"Q6X7", "iMac (24-inch, M1, 2021)"}, + {"Q6X8", "iMac (24-inch, M1, 2021)"}, + {"Q6X9", "iMac (24-inch, M1, 2021)"}, + {"Q6XC", "iMac (24-inch, M1, 2021)"}, + {"Q6XD", "iMac (24-inch, M1, 2021)"}, + {"Q6XF", "iMac (24-inch, M1, 2021)"}, + {"Q6XG", "iMac (24-inch, M1, 2021)"}, + {"Q6XH", "iMac (24-inch, M1, 2021)"}, + {"Q6XJ", "iMac (24-inch, M1, 2021)"}, + {"Q6XK", "iMac (24-inch, M1, 2021)"}, + {"Q6XL", "iMac (24-inch, M1, 2021)"}, + {"Q6XM", "iMac (24-inch, M1, 2021)"}, + {"Q6XN", "iMac (24-inch, M1, 2021)"}, + {"Q6XP", "iMac (24-inch, M1, 2021)"}, + {"Q6XQ", "iMac (24-inch, M1, 2021)"}, + {"Q6XR", "iMac (24-inch, M1, 2021)"}, + {"Q6XT", "iMac (24-inch, M1, 2021)"}, + {"Q6XV", "iMac (24-inch, M1, 2021)"}, + {"Q6XW", "iMac (24-inch, M1, 2021)"}, + {"Q6XX", "iMac (24-inch, M1, 2021)"}, + {"Q6XY", "iMac (24-inch, M1, 2021)"}, {"Q72V", "MacBook Air (Retina, 13-inch, 2020)"}, {"Q72X", "MacBook Air (M1, 2020)"}, {"Q72Y", "MacBook Air (M1, 2020)"}, diff --git a/Resources/Audio/Codecs.plist b/Resources/Audio/Codecs.plist index 8fdccfe2..9185ead3 100644 --- a/Resources/Audio/Codecs.plist +++ b/Resources/Audio/Codecs.plist @@ -399,6 +399,7 @@ ALC269 LayoutIDs + 25 23 24 1 @@ -505,6 +506,7 @@ 35 37 99 + 13 MaxKernel 15 @@ -1580,6 +1582,7 @@ 16 17 18 + 19 66 MaxKernel @@ -2036,7 +2039,9 @@ 31 52 61 + 66 71 + 88 MaxKernel 15 @@ -2052,6 +2057,7 @@ ALC282 LayoutIDs + 69 3 4 13 @@ -2060,6 +2066,7 @@ 27 28 29 + 30 41 43 51 @@ -2145,6 +2152,7 @@ 45 66 88 + 12 MaxKernel 15 diff --git a/Resources/PCI/pci.ids b/Resources/PCI/pci.ids index 81d4c1ce..226467e3 100644 --- a/Resources/PCI/pci.ids +++ b/Resources/PCI/pci.ids @@ -1,8 +1,8 @@ # # List of PCI ID's # -# Version: 2021.11.20 -# Date: 2021-11-20 03:15:02 +# Version: 2021.12.10 +# Date: 2021-12-10 03:15:02 # # Maintained by Albert Pool, Martin Mares, and other volunteers from # the PCI ID Project at https://pci-ids.ucw.cz/. @@ -97,6 +97,23 @@ 0721 Sapphire, Inc. 0731 Jingjia Microelectronics Co Ltd 7200 JM7200 Series GPU + 0731 7201 JM7201 + 0731 7202 JM7202 + 0731 7208 JM7200 + 0731 7212 JM7200 + 0731 7214 JM7500 + 0731 7215 JM7200 + 9200 JM9200 + 920a JH920 + 920b JH920-I + 920c JH920-M + 9210 JM9210 + 9211 JM9210-I + 9230 JM9230 + 9231 JM9231-I + 9250 JM9250 + 930a JH930-I + 930b JH930-M 0777 Ubiquiti Networks, Inc. 0795 Wired Inc. 6663 Butane II (MPEG2 encoder board) @@ -120,6 +137,7 @@ 0905 R1T3 Single T3 Digital Telephony Card 0906 RCB24FXX 24-channel modular analog telephony card 0a06 RCB672FXX 672-channel modular analog telephony card +0ccd Preferred Networks, Inc. 0e11 Compaq Computer Corporation 0001 PCI to EISA Bridge 0002 PCI to ISA Bridge @@ -1017,7 +1035,7 @@ 1551 Arlene 1552 Pooky 1561 Anubis - 15d8 Picasso + 15d8 Picasso/Raven 2 [Radeon Vega Series / Radeon Vega Mobile Series] 103c 8615 Pavilion Laptop 15-cw1xxx 17aa 3181 ThinkCentre M75n IoT 17aa 5124 ThinkPad E595 @@ -2569,6 +2587,7 @@ 174b e164 Radeon HD 6450 1 GB DDR3 174b e180 Radeon HD 6450 174b e201 Radeon HD 6450 + 1787 2311 Radeon HD 6450 17af 8450 Radeon HD 8450 OEM 1b0a 9096 Radeon HD 6450 1b0a 9097 Radeon HD 6450 @@ -3734,6 +3753,7 @@ 73e3 Navi 23 WKS-XL [Radeon PRO W6600] 73e4 Navi 23 USB 73ff Navi 23 [Radeon RX 6600/6600 XT/6600M] + 148c 2412 PowerColor Red Devil RX 6600 XT 7408 Aldebaran 740c Aldebaran 740f Aldebaran @@ -12223,6 +12243,7 @@ 1cfa GP107GL [Quadro P2000] 1cfb GP107GL [Quadro P1000] 1d01 GP108 [GeForce GT 1030] + 1d02 GP108 [GeForce GT 1010] 1d10 GP108M [GeForce MX150] 17aa 225e ThinkPad T480 1d11 GP108M [GeForce MX230] @@ -12886,6 +12907,7 @@ 7038 FPGA Card XC7VX690T 17aa 402f FPGA XC7VX690T-3FFG1157E 8019 Memory controller + 1eec 0201 VSEC10232X Dual-port 100Gb/s Etherent PCIe 8380 Ellips ProfiXpress Profibus Master 8381 Ellips Santos Frame Grabber d154 Copley Controls CAN card (PCI-CAN-02) @@ -15220,7 +15242,7 @@ # Nee Galileo Technology, Inc. 11ab Marvell Technology Group Ltd. 0100 88F3700 [Armada 3700 Family] ARM SoC - 0110 88F8040 PCI Express controller + 0110 88F60x0/88F70x0/88F80x0/CN913x ARM SoC 0146 GT-64010/64010A System Controller 0f53 88E6318 Link Street network controller 11ab MV88SE614x SATA II PCI-E controller @@ -15438,14 +15460,17 @@ 6480 MV64460/64461/64462 System Controller 1775 c200 C2K CompactPCI single board computer 6485 MV64460/64461/64462 System Controller, Revision B + 6560 88F6560 [Avanta] ARM SoC + 6710 88F6710 [Armada 370] ARM SoC 6820 88F6820 [Armada 385] ARM SoC 6828 88F6828 [Armada 388] ARM SoC + 6920 88F6920 [Armada 390] ARM SoC 7042 88SX7042 PCI-e 4-port SATA-II 16b8 434b Tempo SATA E4P 7810 MV78100 [Discovery Innovation] ARM SoC 7820 MV78200 [Discovery Innovation] ARM SoC 7823 MV78230 [Armada XP] ARM SoC - 7846 88F6820 [Armada 385] ARM SoC + 7846 MV78460 [Armada XP] ARM SoC d40f Bobcat3 Ethernet Switch f003 GT-64010 Primary Image Piranha Image Generator 11ac Canon Information Systems Research Aust. @@ -19942,6 +19967,12 @@ b960 Broadcom BCM56960 Switch ASIC # Tomahawk4 b990 BCM56990 Switch ASIC +# Tomahawk4G + b996 BCM56996 Tomahawk4G 106G Switch ASIC +# Tomahawk4GT + b998 BCM56998 Tomahawk4GT 106G Switch ASIC +# Tomahawk4D + b999 BCM56999 Tomahawk4D 106G Switch ASIC c909 BCM78909 Switch ASIC d802 BCM58802 Stingray 50Gb Ethernet SoC 14e4 8021 Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w16GB DRAM (Part No BCM958802A8046C) @@ -20633,6 +20664,8 @@ 021b MT43162 Family [BlueField-3 Lx Secure Flash Recovery] 021c MT43244 Family [BlueField-3 SoC Flash Recovery] 021d MT43244 Family [BlueField-3 Secure Flash Recovery] + 021e CX8 Family [ConnectX-8 Flash Recovery] + 021f CX8 Family [ConnectX-8 Secure Flash Recovery] 024e MT53100 [Spectrum-2, Flash recovery mode] 024f MT53100 [Spectrum-2, Secure Flash recovery mode] 0250 Spectrum-3, Flash recovery mode @@ -20647,9 +20680,11 @@ 0262 MT27710 [ConnectX-4 Lx Programmable] EN 0263 MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN 0264 Innova-2 Flex Burn image + 0270 Spectrum-4L, Flash recovery mode + 0271 Spectrum-4L, RMA + 0274 Spectrum-4C, Flash recovery mode + 0275 Spectrum-4C RMA 0281 NPS-600 Flash Recovery - 0357 Abir GearBox in Flash Recovery Mode - 0358 Abir GearBox in RMA 1002 MT25400 Family [ConnectX-2 Virtual Function] 1003 MT27500 Family [ConnectX-3] 1014 04b5 PCIe3 40GbE RoCE Converged Host Bus Adapter for Power @@ -20745,6 +20780,7 @@ 101f MT2894 Family [ConnectX-6 Lx] 1020 MT28860 1021 MT2910 Family [ConnectX-7] + 1023 CX8 Family [ConnectX-8] 1974 MT28800 Family [ConnectX-5 PCIe Bridge] 1975 MT416842 Family [BlueField SoC PCIe Bridge] 1976 MT28908 Family [ConnectX-6 PCIe Bridge] @@ -20753,10 +20789,12 @@ 1979 MT2910 Family [ConnectX-7 PCIe Bridge] 197a MT43162 Family [BlueField-3 Lx SoC PCIe Bridge] 197b MT43244 Family [BlueField-3 SoC PCIe Bridge] + 197c CX8 Family [ConnectX-8 PCIe Bridge] 2020 MT2892 Family [ConnectX-6 Dx Emulated PCIe Bridge] 2021 MT42822 Family [BlueField-2 SoC Emulated PCIe Bridge] 2023 MT2910 Family [ConnectX-7 Emulated PCIe Bridge] 2024 MT43244 Family [BlueField-3 SoC Emulated PCIe Bridge] + 2025 CX8 Family [ConnectX-8 Emulated PCIe Bridge] 4117 MT27712A0-FDCF-AE 1bd4 0039 SN10XMP2P25 1bd4 003a 25G SFP28 SP EO251FM9 Adapter @@ -20833,6 +20871,8 @@ cf6c MT53100 [Spectrum-2] cf70 Spectrum-3 cf80 Spectrum-4 + cf82 Spectrum-4L + cf84 Spectrum-4C d2f0 Quantum HDR (200Gbps) switch d2f2 Quantum-2 NDR (400Gbps) switch 15b4 CCI/TRIAD @@ -20868,6 +20908,7 @@ 1414 500b Xbox Series X 500d WD Ultrastar DC SN340 NVMe SSD 5011 WD PC SN810 / Black SN850 NVMe SSD + 501a WD Blue SN570 NVMe SSD 15b8 ADDI-DATA GmbH 1001 APCI1516 SP controller (16 digi outputs) 1003 APCI1032 SP controller (32 digi inputs w/ opto coupler) @@ -21409,6 +21450,7 @@ 003e QCA6174 802.11ac Wireless Network Adapter 1a56 143a Killer 1435 Wireless-AC 1a56 1525 Killer N1525 Wireless-AC + 1a56 1535 Killer Wireless-n/a/ac 1535 Wireless Network Adapter 0040 QCA9980/9990 802.11ac Wireless Network Adapter 0041 QCA6164 802.11ac Wireless Network Adapter 0042 QCA9377 802.11ac Wireless Network Adapter @@ -24012,6 +24054,7 @@ 1dc5 FADU Inc. 1dcd Liqid Inc. 1dcf Beijing Sinead Technology Co., Ltd. +1dd3 Sage Microelectronics Corp. 1dd8 Pensando Systems 0002 DSC2 Elba Upstream Port 1dd8 5001 DSC2-200 50/100/200G 2-port 32G RAM 64G eMMC G2 Services Card @@ -24111,6 +24154,12 @@ 1000 IO Memory Controller 2000 NoLoad Hardware Development Kit 3000 eBPF-based PCIe Accelerator +1ded Alibaba (China) Co., Ltd. + 8000 M1 Root Port + 8001 ACC-RCiEP + 8002 RCiEP VF + 8003 RCEC PF + 8004 RCEC VF 1dee Biwin Storage Technology Co., Ltd. 1def Ampere Computing, LLC e005 eMAG PCI Express Root Port 0 @@ -24496,6 +24545,7 @@ 1783 AS-i 3.0 cPCI Master 1922 AS-i 3.0 PCI Master 3475 Arista Networks, Inc. +34ba Ice Lake-LP PCI Express Root Port #3 3513 ARCOM Control Systems Ltd 37d9 ITD Firm ltd. 1138 SCHD-PH-8 Phase detector @@ -25407,6 +25457,8 @@ 8086 01f7 SCRU32 # uninitialized SRCU32 RAID Controller 061f 80303 I/O Processor + 0684 H470 Chipset LPC/eSPI Controller + 0687 Q470 Chipset LPC/eSPI Controller 068d Comet Lake LPC Controller 06a3 Comet Lake PCH SMBus Controller 06a4 Comet Lake PCH SPI Controller @@ -27069,6 +27121,7 @@ 8086 00a2 Ethernet Server Adapter I350-T2 8086 00a3 Ethernet Network Adapter I350-T4 for OCP NIC 3.0 8086 00aa Ethernet Network Adapter I350-T4 for OCP NIC 3.0 + 8086 4017 Ethernet Network Adapter I350-T4 for OCP NIC 3.0 8086 5001 Ethernet Server Adapter I350-T4 8086 5002 Ethernet Server Adapter I350-T2 8086 5003 Ethernet 1G 4P I350-t OCP @@ -31111,6 +31164,7 @@ 34ab Ice Lake-LP Serial IO SPI Controller #1 34b0 Ice Lake-LP PCI Express Root Port #9 34b7 Ice Lake-LP PCI Express Root Port #16 + 34ba Ice Lake-LP PCI Express Root Port #3 34bc Ice Lake-LP PCI Express Root Port #5 34c5 Ice Lake-LP Serial IO I2c Controller #4 34c6 Ice Lake-LP Serial IO I2c Controller #5 @@ -31366,6 +31420,9 @@ 17aa 4025 Ethernet Connection X722 for 10GbE SFP+ 37d4 Ethernet Connection X722 for 10GbE QSFP+ 37d9 X722 Hyper-V Virtual Function + 3882 Ice Lake LPC Controller + 38a4 Ice Lake SPI Controller + 38e0 Ice Lake Management Engine Interface 3a00 82801JD/DO (ICH10 Family) 4-port SATA IDE Controller 3a02 82801JD/DO (ICH10 Family) SATA AHCI Controller 3a05 82801JD/DO (ICH10 Family) SATA RAID Controller @@ -31745,7 +31802,7 @@ 3e89 8th Gen Core Processor PCIe Controller (x4) 3e90 CoffeeLake-S GT1 [UHD Graphics 610] 3e91 CoffeeLake-S GT2 [UHD Graphics 630] - 3e92 CometLake-S GT2 [UHD Graphics 630] + 3e92 CoffeeLake-S GT2 [UHD Graphics 630] 1028 0869 Vostro 3470 3e93 CoffeeLake-S GT1 [UHD Graphics 610] 3e96 CoffeeLake-S GT2 [UHD Graphics P630] @@ -32454,6 +32511,7 @@ 8a0d Ice Lake Thunderbolt 3 NHI #1 8a12 Ice Lake-LP Processor Host Bridge/DRAM Registers 8a13 Ice Lake Thunderbolt 3 USB Controller + 8a14 Ice Lake Processor Host Bridge/DRAM Registers 8a17 Ice Lake Thunderbolt 3 NHI #0 8a19 Image Signal Processor 8a1d Ice Lake Thunderbolt 3 PCI Express Root Port #0 @@ -32739,6 +32797,7 @@ 9a49 TigerLake-LP GT2 [Iris Xe Graphics] 9a60 TigerLake-H GT1 [UHD Graphics] 9a68 TigerLake-H GT1 [UHD Graphics] + 9b33 Comet Lake-S 6c Host Bridge/DRAM Controller 9b41 CometLake-U GT2 [UHD Graphics] 1028 09bd Latitude 7310 1028 09be Latitude 7410 @@ -33311,6 +33370,7 @@ a2f0 200 Series PCH HD Audio 1462 7a72 H270 PC MATE 1462 fa72 H270 PC MATE + a303 H310 Chipset LPC/eSPI Controller a304 H370 Chipset LPC/eSPI Controller 1028 0869 Vostro 3470 a305 Z390 Chipset LPC/eSPI Controller @@ -33371,10 +33431,19 @@ a379 Cannon Lake PCH Thermal Controller 1028 0869 Vostro 3470 a382 400 Series Chipset Family SATA AHCI Controller + a394 Comet Lake PCI Express Root Port #05 + a397 Comet Lake PCI Express Root Port #08 + a398 Comet Lake PCI Express Root Port 9 + a39a Comet Lake PCI Express Root Port 11 a3a1 Memory controller a3a3 Comet Lake PCH-V SMBus Host Controller a3af Comet Lake PCH-V USB Controller a3b1 Comet Lake PCH-V Thermal Subsystem + a3ba Comet Lake PCH-V HECI Controller + a3c8 B460 Chipset LPC/eSPI Controller + a3da H410 Chipset LPC/eSPI Controller + a3eb Comet Lake PCI Express Root Port #21 + a3f0 Comet Lake PCH-V cAVS a620 6400/6402 Advanced Memory Buffer (AMB) abc0 Omni-Path Fabric Switch Silicon 100 Series b152 21152 PCI-to-PCI Bridge @@ -34598,6 +34667,7 @@ C 0c Serial bus controller 02 BT (Block Transfer) 08 SERCOS interface 09 CANBUS + 80 Serial bus controller C 0d Wireless controller 00 IRDA controller 01 Consumer IR controller