1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212 |
- /*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind.
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
- * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
- * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
- * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
- * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
- * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
- * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
- * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
- * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
- #include <ipmitool/ipmi.h>
- #include <ipmitool/log.h>
- #include <ipmitool/helper.h>
- #include <ipmitool/ipmi_intf.h>
- #include <ipmitool/ipmi_fru.h>
- #include <ipmitool/ipmi_mc.h>
- #include <ipmitool/ipmi_sdr.h>
- #include <ipmitool/ipmi_strings.h> /* IANA id strings */
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <errno.h>
- #if HAVE_CONFIG_H
- # include <config.h>
- #endif
- #define FRU_MULTIREC_CHUNK_SIZE (255 + sizeof(struct fru_multirec_header))
- static const char *section_id[4] = {
- "Internal Use Section",
- "Chassis Section",
- "Board Section",
- "Product Section"
- };
- /* From lib/dimm_spd.c: */
- int
- ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id);
- /* From src/plugins/ipmi_intf.c: */
- void
- ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size);
- void
- ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size);
- extern int verbose;
- static void ipmi_fru_read_to_bin(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
- static void ipmi_fru_write_from_bin(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
- static int ipmi_fru_upg_ekeying(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
- static int ipmi_fru_get_multirec_location_from_fru(struct ipmi_intf * intf, uint8_t fruId,
- struct fru_info *pFruInfo, uint32_t * pRetLocation,
- uint32_t * pRetSize);
- static int ipmi_fru_get_multirec_from_file(char * pFileName, uint8_t * pBufArea,
- uint32_t size, uint32_t offset);
- static int ipmi_fru_get_multirec_size_from_file(char * pFileName, uint32_t * pSize, uint32_t * pOffset);
- int ipmi_fru_get_adjust_size_from_buffer(uint8_t *pBufArea, uint32_t *pSize);
- static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length);
- static int ipmi_fru_set_field_string(struct ipmi_intf * intf, unsigned
- char fruId, uint8_t f_type, uint8_t f_index, char *f_string);
- static int
- ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
- struct fru_info fru, struct fru_header header,
- uint8_t f_type, uint8_t f_index, char *f_string);
- static void
- fru_area_print_multirec_bloc(struct ipmi_intf * intf, struct fru_info * fru,
- uint8_t id, uint32_t offset);
- int
- read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
- uint32_t offset, uint32_t length, uint8_t *frubuf);
- void free_fru_bloc(t_ipmi_fru_bloc *bloc);
- /* get_fru_area_str - Parse FRU area string from raw data
- *
- * @data: raw FRU data
- * @offset: offset into data for area
- *
- * returns pointer to FRU area string
- */
- char * get_fru_area_str(uint8_t * data, uint32_t * offset)
- {
- static const char bcd_plus[] = "0123456789 -.:,_";
- char * str;
- int len, off, size, i, j, k, typecode;
- union {
- uint32_t bits;
- char chars[4];
- } u;
- size = 0;
- off = *offset;
- /* bits 6:7 contain format */
- typecode = ((data[off] & 0xC0) >> 6);
- // printf("Typecode:%i\n", typecode);
- /* bits 0:5 contain length */
- len = data[off++];
- len &= 0x3f;
- switch (typecode) {
- case 0: /* 00b: binary/unspecified */
- /* hex dump -> 2x length */
- size = (len*2);
- break;
- case 2: /* 10b: 6-bit ASCII */
- /* 4 chars per group of 1-3 bytes */
- size = ((((len+2)*4)/3) & ~3);
- break;
- case 3: /* 11b: 8-bit ASCII */
- case 1: /* 01b: BCD plus */
- /* no length adjustment */
- size = len;
- break;
- }
- if (size < 1) {
- *offset = off;
- return NULL;
- }
- str = malloc(size+1);
- if (str == NULL)
- return NULL;
- memset(str, 0, size+1);
- if (len == 0) {
- str[0] = '\0';
- *offset = off;
- return str;
- }
- switch (typecode) {
- case 0: /* Binary */
- strncpy(str, buf2str(&data[off], len), len*2);
- break;
- case 1: /* BCD plus */
- for (k=0; k<len; k++)
- str[k] = bcd_plus[(data[off+k] & 0x0f)];
- str[k] = '\0';
- break;
- case 2: /* 6-bit ASCII */
- for (i=j=0; i<len; i+=3) {
- u.bits = 0;
- k = ((len-i) < 3 ? (len-i) : 3);
- #if WORDS_BIGENDIAN
- u.chars[3] = data[off+i];
- u.chars[2] = (k > 1 ? data[off+i+1] : 0);
- u.chars[1] = (k > 2 ? data[off+i+2] : 0);
- #define CHAR_IDX 3
- #else
- memcpy((void *)&u.bits, &data[off+i], k);
- #define CHAR_IDX 0
- #endif
- for (k=0; k<4; k++) {
- str[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20);
- u.bits >>= 6;
- }
- }
- str[j] = '\0';
- break;
- case 3:
- memcpy(str, &data[off], len);
- str[len] = '\0';
- break;
- }
- off += len;
- *offset = off;
- return str;
- }
- /* is_valid_filename - checks file/path supplied by user
- *
- * input_filename - user input string
- *
- * returns 0 if path is ok
- * returns (-1) if path is NULL
- * returns (-2) if path is too short
- * returns (-3) if path is too long
- */
- int
- is_valid_filename(const char *input_filename)
- {
- if (input_filename == NULL) {
- lprintf(LOG_ERR, "ERROR: NULL pointer passed.");
- return (-1);
- }
- if (strlen(input_filename) < 1) {
- lprintf(LOG_ERR, "File/path is invalid.");
- return (-2);
- }
- if (strlen(input_filename) >= 512) {
- lprintf(LOG_ERR, "File/path must be shorter than 512 bytes.");
- return (-3);
- }
- return 0;
- } /* is_valid_filename() */
- /* build_fru_bloc - build fru bloc for write protection
- *
- * @intf: ipmi interface
- * @fru_info: information about FRU device
- * @id : Fru id
- * @soffset : Source offset (from buffer)
- * @doffset : Destination offset (in device)
- * @length : Size of data to write (in bytes)
- * @pFrubuf : Pointer on data to write
- *
- * returns 0 on success
- * returns -1 on error
- */
- #define FRU_NUM_BLOC_COMMON_HEADER 6
- t_ipmi_fru_bloc *
- build_fru_bloc(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id)
- {
- t_ipmi_fru_bloc * p_first, * p_bloc, * p_new;
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- struct fru_header header;
- struct fru_multirec_header rec_hdr;
- uint8_t msg_data[4];
- uint32_t off;
- uint16_t i;
- /*
- * get COMMON Header format
- */
- msg_data[0] = id;
- msg_data[1] = 0;
- msg_data[2] = 0;
- msg_data[3] = 8;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_DATA;
- req.msg.data = msg_data;
- req.msg.data_len = 4;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, " Device not present (No Response)");
- return NULL;
- }
- if (rsp->ccode > 0) {
- lprintf(LOG_ERR," Device not present (%s)",
- val2str(rsp->ccode, completion_code_vals));
- return NULL;
- }
- if (verbose > 1) {
- printbuf(rsp->data, rsp->data_len, "FRU DATA");
- }
- memcpy(&header, rsp->data + 1, 8);
- /* verify header checksum */
- if (ipmi_csum((uint8_t *)&header, 8)) {
- lprintf(LOG_ERR, " Bad header checksum");
- return NULL;
- }
- if (header.version != 1) {
- lprintf(LOG_ERR, " Unknown FRU header version 0x%02x", header.version);
- return NULL;
- }
- /******************************************
- Malloc and fill up the bloc contents
- *******************************************/
- // Common header
- p_first = malloc(sizeof(struct ipmi_fru_bloc));
- if (!p_first) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- return NULL;
- }
- p_bloc = p_first;
- p_bloc->next = NULL;
- p_bloc->start= 0;
- p_bloc->size = fru->size;
- strcpy((char *)p_bloc->blocId, "Common Header Section");
- for (i = 0; i < 4; i++) {
- if (header.offsets[i]) {
- p_new = malloc(sizeof(struct ipmi_fru_bloc));
- if (!p_new) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- free_fru_bloc(p_first);
- return NULL;
- }
- p_new->next = NULL;
- p_new->start = header.offsets[i] * 8;
- p_new->size = fru->size - p_new->start;
- strncpy((char *)p_new->blocId, section_id[i], sizeof(p_new->blocId));
- /* Make sure string is null terminated */
- p_new->blocId[sizeof(p_new->blocId)-1] = 0;
- p_bloc->next = p_new;
- p_bloc->size = p_new->start - p_bloc->start;
- p_bloc = p_new;
- }
- }
- // Multi
- if (header.offset.multi) {
- off = header.offset.multi * 8;
- do {
- /*
- * check for odd offset for the case of fru devices
- * accessed by words
- */
- if (fru->access && (off & 1)) {
- lprintf(LOG_ERR, " Unaligned offset for a block: %d", off);
- /* increment offset */
- off++;
- break;
- }
- if (read_fru_area(intf, fru, id, off, 5,
- (uint8_t *) &rec_hdr) < 0) {
- break;
- }
- p_new = malloc(sizeof(struct ipmi_fru_bloc));
- if (!p_new) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- free_fru_bloc(p_first);
- return NULL;
- }
- p_new->next = NULL;
- p_new->start = off;
- p_new->size = fru->size - p_new->start;
- sprintf((char *)p_new->blocId, "Multi-Rec Area: Type %i",
- rec_hdr.type);
- p_bloc->next = p_new;
- p_bloc->size = p_new->start - p_bloc->start;
- p_bloc = p_new;
- off += rec_hdr.len + sizeof(struct fru_multirec_header);
- /* verify record header */
- if (ipmi_csum((uint8_t *)&rec_hdr,
- sizeof(struct fru_multirec_header))) {
- /* can't reliably judge for the rest space */
- break;
- }
- } while (!(rec_hdr.format & 0x80) && (off < fru->size));
- lprintf(LOG_DEBUG,"Multi-Record area ends at: %i (%xh)", off, off);
- if (fru->size > off) {
- // Bloc for remaining space
- p_new = malloc(sizeof(struct ipmi_fru_bloc));
- if (!p_new) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- free_fru_bloc(p_first);
- return NULL;
- }
- p_new->next = NULL;
- p_new->start = off;
- p_new->size = fru->size - p_new->start;
- strcpy((char *)p_new->blocId, "Unused space");
- p_bloc->next = p_new;
- p_bloc->size = p_new->start - p_bloc->start;
- }
- }
- /* Dump blocs */
- for(p_bloc = p_first, i = 0; p_bloc; p_bloc = p_bloc->next) {
- lprintf(LOG_DEBUG ,"Bloc Numb : %i", i++);
- lprintf(LOG_DEBUG ,"Bloc Id : %s", p_bloc->blocId);
- lprintf(LOG_DEBUG ,"Bloc Start: %i", p_bloc->start);
- lprintf(LOG_DEBUG ,"Bloc Size : %i", p_bloc->size);
- lprintf(LOG_DEBUG ,"");
- }
- return p_first;
- }
- void
- free_fru_bloc(t_ipmi_fru_bloc *bloc)
- {
- t_ipmi_fru_bloc * del;
- while (bloc) {
- del = bloc;
- bloc = bloc->next;
- free(del);
- del = NULL;
- }
- }
- /*
- * write FRU[doffset:length] from the pFrubuf[soffset:length]
- * rc=1 on success
- **/
- int
- write_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
- uint16_t soffset, uint16_t doffset,
- uint16_t length, uint8_t *pFrubuf)
- {
- uint16_t tmp, finish;
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- uint8_t msg_data[255+3];
- uint16_t writeLength;
- uint16_t found_bloc = 0;
- finish = doffset + length; /* destination offset */
- if (finish > fru->size)
- {
- lprintf(LOG_ERROR, "Return error");
- return -1;
- }
- if (fru->access && ((doffset & 1) || (length & 1))) {
- lprintf(LOG_ERROR, "Odd offset or length specified");
- return (-1);
- }
- t_ipmi_fru_bloc * fru_bloc = build_fru_bloc(intf, fru, id);
- t_ipmi_fru_bloc * saved_fru_bloc = fru_bloc;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = SET_FRU_DATA;
- req.msg.data = msg_data;
- /* initialize request size only once */
- if (fru->max_write_size == 0) {
- uint16_t max_rq_size = ipmi_intf_get_max_request_data_size(intf);
- /* validate lower bound of the maximum request data size */
- if (max_rq_size <= 3) {
- lprintf(LOG_ERROR, "Maximum request size is too small to send "
- "a write request");
- return -1;
- }
- /*
- * Write FRU Info command returns the number of written bytes in
- * a single byte field.
- */
- if (max_rq_size - 3 > 255) {
- /* Limit the max write size with 255 bytes. */
- fru->max_write_size = 255;
- } else {
- /* subtract 1 byte for FRU ID an 2 bytes for offset */
- fru->max_write_size = max_rq_size - 3;
- }
- /* check word access */
- if (fru->access) {
- fru->max_write_size &= ~1;
- }
- }
- do {
- uint16_t end_bloc;
- uint8_t protected_bloc = 0;
- /* Write per bloc, try to find the end of a bloc*/
- while (fru_bloc && fru_bloc->start + fru_bloc->size <= doffset) {
- fru_bloc = fru_bloc->next;
- found_bloc++;
- }
- if (fru_bloc && fru_bloc->start + fru_bloc->size < finish) {
- end_bloc = fru_bloc->start + fru_bloc->size;
- } else {
- end_bloc = finish;
- }
- /* calculate write length */
- tmp = end_bloc - doffset;
- /* check that write length is more than maximum request size */
- if (tmp > fru->max_write_size) {
- writeLength = fru->max_write_size;
- } else {
- writeLength = tmp;
- }
- /* copy fru data */
- memcpy(&msg_data[3], pFrubuf + soffset, writeLength);
- /* check word access */
- if (fru->access) {
- writeLength &= ~1;
- }
- tmp = doffset;
- if (fru->access) {
- tmp >>= 1;
- }
- msg_data[0] = id;
- msg_data[1] = (uint8_t)tmp;
- msg_data[2] = (uint8_t)(tmp >> 8);
- req.msg.data_len = writeLength + 3;
- if(fru_bloc) {
- lprintf(LOG_INFO,"Writing %d bytes (Bloc #%i: %s)",
- writeLength, found_bloc, fru_bloc->blocId);
- } else {
- lprintf(LOG_INFO,"Writing %d bytes", writeLength);
- }
- rsp = intf->sendrecv(intf, &req);
- if (!rsp) {
- break;
- }
- if (rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) {
- if (fru->max_write_size > 8) {
- fru->max_write_size -= 8;
- lprintf(LOG_INFO, "Retrying FRU write with request size %d",
- fru->max_write_size);
- continue;
- }
- } else if(rsp->ccode == 0x80) {
- rsp->ccode = 0;
- // Write protected section
- protected_bloc = 1;
- }
- if (rsp->ccode > 0)
- break;
- if (protected_bloc == 0) {
- // Write OK, bloc not protected, continue
- lprintf(LOG_INFO,"Wrote %d bytes", writeLength);
- doffset += writeLength;
- soffset += writeLength;
- } else {
- if(fru_bloc) {
- // Bloc protected, advise user and jump over protected bloc
- lprintf(LOG_INFO,
- "Bloc [%s] protected at offset: %i (size %i bytes)",
- fru_bloc->blocId, fru_bloc->start, fru_bloc->size);
- lprintf(LOG_INFO,"Jumping over this bloc");
- } else {
- lprintf(LOG_INFO,
- "Remaining FRU is protected following offset: %i",
- doffset);
- }
- soffset += end_bloc - doffset;
- doffset = end_bloc;
- }
- } while (doffset < finish);
- if (saved_fru_bloc) {
- free_fru_bloc(saved_fru_bloc);
- }
- return doffset >= finish;
- }
- /* read_fru_area - fill in frubuf[offset:length] from the FRU[offset:length]
- *
- * @intf: ipmi interface
- * @fru: fru info
- * @id: fru id
- * @offset: offset into buffer
- * @length: how much to read
- * @frubuf: buffer read into
- *
- * returns -1 on error
- * returns 0 if successful
- */
- int
- read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
- uint32_t offset, uint32_t length, uint8_t *frubuf)
- {
- uint32_t off = offset, tmp, finish;
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- uint8_t msg_data[4];
- if (offset > fru->size) {
- lprintf(LOG_ERR, "Read FRU Area offset incorrect: %d > %d",
- offset, fru->size);
- return -1;
- }
- finish = offset + length;
- if (finish > fru->size) {
- finish = fru->size;
- lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
- "Adjusting to %d",
- offset + length, finish - offset);
- }
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_DATA;
- req.msg.data = msg_data;
- req.msg.data_len = 4;
- if (fru->max_read_size == 0) {
- uint16_t max_rs_size = ipmi_intf_get_max_response_data_size(intf) - 1;
- /* validate lower bound of the maximum response data size */
- if (max_rs_size <= 1) {
- lprintf(LOG_ERROR, "Maximum response size is too small to send "
- "a read request");
- return -1;
- }
- /*
- * Read FRU Info command may read up to 255 bytes of data.
- */
- if (max_rs_size - 1 > 255) {
- /* Limit the max read size with 255 bytes. */
- fru->max_read_size = 255;
- } else {
- /* subtract 1 byte for bytes count */
- fru->max_read_size = max_rs_size - 1;
- }
- /* check word access */
- if (fru->access) {
- fru->max_read_size &= ~1;
- }
- }
- do {
- tmp = fru->access ? off >> 1 : off;
- msg_data[0] = id;
- msg_data[1] = (uint8_t)(tmp & 0xff);
- msg_data[2] = (uint8_t)(tmp >> 8);
- tmp = finish - off;
- if (tmp > fru->max_read_size)
- msg_data[3] = (uint8_t)fru->max_read_size;
- else
- msg_data[3] = (uint8_t)tmp;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_NOTICE, "FRU Read failed");
- break;
- }
- if (rsp->ccode > 0) {
- /* if we get C7h or C8h or CAh return code then we requested too
- * many bytes at once so try again with smaller size */
- if ((rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca)
- && fru->max_read_size > 8) {
- if (fru->max_read_size > 32) {
- /* subtract read length more aggressively */
- fru->max_read_size -= 8;
- } else {
- /* subtract length less aggressively */
- fru->max_read_size--;
- }
- lprintf(LOG_INFO, "Retrying FRU read with request size %d",
- fru->max_read_size);
- continue;
- }
- lprintf(LOG_NOTICE, "FRU Read failed: %s",
- val2str(rsp->ccode, completion_code_vals));
- break;
- }
- tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
- memcpy(frubuf, rsp->data + 1, tmp);
- off += tmp;
- frubuf += tmp;
- /* sometimes the size returned in the Info command
- * is too large. return 0 so higher level function
- * still attempts to parse what was returned */
- if (tmp == 0 && off < finish) {
- return 0;
- }
- } while (off < finish);
- if (off < finish) {
- return -1;
- }
- return 0;
- }
- /* read_fru_area - fill in frubuf[offset:length] from the FRU[offset:length]
- *
- * @intf: ipmi interface
- * @fru: fru info
- * @id: fru id
- * @offset: offset into buffer
- * @length: how much to read
- * @frubuf: buffer read into
- *
- * returns -1 on error
- * returns 0 if successful
- */
- int
- read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
- uint32_t offset, uint32_t length, uint8_t *frubuf)
- {
- static uint32_t fru_data_rqst_size = 20;
- uint32_t off = offset, tmp, finish;
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- uint8_t msg_data[4];
- if (offset > fru->size) {
- lprintf(LOG_ERR, "Read FRU Area offset incorrect: %d > %d",
- offset, fru->size);
- return -1;
- }
- finish = offset + length;
- if (finish > fru->size) {
- finish = fru->size;
- lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
- "Adjusting to %d",
- offset + length, finish - offset);
- }
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_DATA;
- req.msg.data = msg_data;
- req.msg.data_len = 4;
- #ifdef LIMIT_ALL_REQUEST_SIZE
- if (fru_data_rqst_size > 16)
- #else
- if (fru->access && fru_data_rqst_size > 16)
- #endif
- fru_data_rqst_size = 16;
- do {
- tmp = fru->access ? off >> 1 : off;
- msg_data[0] = id;
- msg_data[1] = (uint8_t)(tmp & 0xff);
- msg_data[2] = (uint8_t)(tmp >> 8);
- tmp = finish - off;
- if (tmp > fru_data_rqst_size)
- msg_data[3] = (uint8_t)fru_data_rqst_size;
- else
- msg_data[3] = (uint8_t)tmp;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_NOTICE, "FRU Read failed");
- break;
- }
- if (rsp->ccode > 0) {
- /* if we get C7 or C8 or CA return code then we requested too
- * many bytes at once so try again with smaller size */
- if ((rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) &&
- (--fru_data_rqst_size > 8)) {
- lprintf(LOG_INFO, "Retrying FRU read with request size %d",
- fru_data_rqst_size);
- continue;
- }
- lprintf(LOG_NOTICE, "FRU Read failed: %s",
- val2str(rsp->ccode, completion_code_vals));
- break;
- }
- tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
- memcpy((frubuf + off)-offset, rsp->data + 1, tmp);
- off += tmp;
- /* sometimes the size returned in the Info command
- * is too large. return 0 so higher level function
- * still attempts to parse what was returned */
- if (tmp == 0 && off < finish)
- return 0;
- } while (off < finish);
- if (off < finish)
- return -1;
- return 0;
- }
- static void
- fru_area_print_multirec_bloc(struct ipmi_intf * intf, struct fru_info * fru,
- uint8_t id, uint32_t offset)
- {
- uint8_t * fru_data = NULL;
- uint32_t i;
- struct fru_multirec_header * h;
- uint32_t last_off, len;
- i = last_off = offset;
- fru_data = malloc(fru->size + 1);
- if (fru_data == NULL) {
- lprintf(LOG_ERR, " Out of memory!");
- return;
- }
- memset(fru_data, 0, fru->size + 1);
- do {
- h = (struct fru_multirec_header *) (fru_data + i);
- // read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time
- if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
- {
- len = fru->size - last_off;
- if (len > FRU_MULTIREC_CHUNK_SIZE)
- len = FRU_MULTIREC_CHUNK_SIZE;
- if (read_fru_area(intf, fru, id, last_off, len, fru_data) < 0)
- break;
- last_off += len;
- }
- //printf("Bloc Numb : %i\n", counter);
- printf("Bloc Start: %i\n", i);
- printf("Bloc Size : %i\n", h->len);
- printf("\n");
- i += h->len + sizeof (struct fru_multirec_header);
- } while (!(h->format & 0x80));
- i = offset;
- do {
- h = (struct fru_multirec_header *) (fru_data + i);
- printf("Bloc Start: %i\n", i);
- printf("Bloc Size : %i\n", h->len);
- printf("\n");
- i += h->len + sizeof (struct fru_multirec_header);
- } while (!(h->format & 0x80));
- lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)",i,i);
- free(fru_data);
- fru_data = NULL;
- }
- /* fru_area_print_chassis - Print FRU Chassis Area
- *
- * @intf: ipmi interface
- * @fru: fru info
- * @id: fru id
- * @offset: offset pointer
- */
- static void
- fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru,
- uint8_t id, uint32_t offset)
- {
- char * fru_area;
- uint8_t * fru_data;
- uint32_t fru_len, i;
- uint8_t tmp[2];
- fru_len = 0;
- /* read enough to check length field */
- if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
- fru_len = 8 * tmp[1];
- }
- if (fru_len == 0) {
- return;
- }
- fru_data = malloc(fru_len);
- if (fru_data == NULL) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- return;
- }
- memset(fru_data, 0, fru_len);
- /* read in the full fru */
- if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
- free(fru_data);
- fru_data = NULL;
- return;
- }
- /*
- * skip first two bytes which specify
- * fru area version and fru area length
- */
- i = 2;
- printf(" Chassis Type : %s\n",
- chassis_type_desc[fru_data[i] >
- (sizeof(chassis_type_desc)/sizeof(chassis_type_desc[0])) - 1 ?
- 2 : fru_data[i]]);
- i++;
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Chassis Part Number : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Chassis Serial : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- /* read any extra fields */
- while ((fru_data[i] != 0xc1) && (i < fru_len))
- {
- int j = i;
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Chassis Extra : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- if (i == j) {
- break;
- }
- }
- if (fru_data != NULL) {
- free(fru_data);
- fru_data = NULL;
- }
- }
- /* fru_area_print_board - Print FRU Board Area
- *
- * @intf: ipmi interface
- * @fru: fru info
- * @id: fru id
- * @offset: offset pointer
- */
- static void
- fru_area_print_board(struct ipmi_intf * intf, struct fru_info * fru,
- uint8_t id, uint32_t offset)
- {
- char * fru_area;
- uint8_t * fru_data;
- uint32_t fru_len;
- uint32_t i;
- time_t tval;
- uint8_t tmp[2];
- fru_len = 0;
- /* read enough to check length field */
- if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
- fru_len = 8 * tmp[1];
- }
- if (fru_len <= 0) {
- return;
- }
- fru_data = malloc(fru_len);
- if (fru_data == NULL) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- return;
- }
- memset(fru_data, 0, fru_len);
- /* read in the full fru */
- if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
- free(fru_data);
- fru_data = NULL;
- return;
- }
- /*
- * skip first three bytes which specify
- * fru area version, fru area length
- * and fru board language
- */
- i = 3;
- tval=((fru_data[i+2] << 16) + (fru_data[i+1] << 8) + (fru_data[i]));
- tval=tval * 60;
- tval=tval + secs_from_1970_1996;
- printf(" Board Mfg Date : %s", asctime(localtime(&tval)));
- i += 3; /* skip mfg. date time */
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Board Mfg : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Board Product : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Board Serial : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Board Part Number : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0 && verbose > 0) {
- printf(" Board FRU ID : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- /* read any extra fields */
- while ((fru_data[i] != 0xc1) && (i < fru_len))
- {
- int j = i;
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Board Extra : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- if (i == j)
- break;
- }
- if (fru_data != NULL) {
- free(fru_data);
- fru_data = NULL;
- }
- }
- /* fru_area_print_product - Print FRU Product Area
- *
- * @intf: ipmi interface
- * @fru: fru info
- * @id: fru id
- * @offset: offset pointer
- */
- static void
- fru_area_print_product(struct ipmi_intf * intf, struct fru_info * fru,
- uint8_t id, uint32_t offset)
- {
- char * fru_area;
- uint8_t * fru_data;
- uint32_t fru_len, i;
- uint8_t tmp[2];
- fru_len = 0;
- /* read enough to check length field */
- if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
- fru_len = 8 * tmp[1];
- }
- if (fru_len == 0) {
- return;
- }
- fru_data = malloc(fru_len);
- if (fru_data == NULL) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- return;
- }
- memset(fru_data, 0, fru_len);
- /* read in the full fru */
- if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
- free(fru_data);
- fru_data = NULL;
- return;
- }
- /*
- * skip first three bytes which specify
- * fru area version, fru area length
- * and fru board language
- */
- i = 3;
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Product Manufacturer : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Product Name : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Product Part Number : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Product Version : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Product Serial : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Product Asset Tag : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0 && verbose > 0) {
- printf(" Product FRU ID : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- /* read any extra fields */
- while ((fru_data[i] != 0xc1) && (i < fru_len))
- {
- int j = i;
- fru_area = get_fru_area_str(fru_data, &i);
- if (fru_area != NULL) {
- if (strlen(fru_area) > 0) {
- printf(" Product Extra : %s\n", fru_area);
- }
- free(fru_area);
- fru_area = NULL;
- }
- if (i == j)
- break;
- }
- if (fru_data != NULL) {
- free(fru_data);
- fru_data = NULL;
- }
- }
- /* fru_area_print_multirec - Print FRU Multi Record Area
- *
- * @intf: ipmi interface
- * @fru: fru info
- * @id: fru id
- * @offset: offset pointer
- */
- static void
- fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
- uint8_t id, uint32_t offset)
- {
- uint8_t * fru_data;
- struct fru_multirec_header * h;
- struct fru_multirec_powersupply * ps;
- struct fru_multirec_dcoutput * dc;
- struct fru_multirec_dcload * dl;
- uint16_t peak_capacity;
- uint8_t peak_hold_up_time;
- uint32_t last_off;
- last_off = offset;
- fru_data = malloc(FRU_MULTIREC_CHUNK_SIZE);
- if (fru_data == NULL) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- return;
- }
- memset(fru_data, 0, FRU_MULTIREC_CHUNK_SIZE);
- h = (struct fru_multirec_header *) (fru_data);
- do {
- if (read_fru_area(intf, fru, id, last_off, sizeof(*h), fru_data) < 0) {
- break;
- }
- if (h->len && read_fru_area(intf, fru, id,
- last_off + sizeof(*h), h->len, fru_data + sizeof(*h)) < 0) {
- break;
- }
- last_off += h->len + sizeof(*h);
- switch (h->type) {
- case FRU_RECORD_TYPE_POWER_SUPPLY_INFORMATION:
- ps = (struct fru_multirec_powersupply *)
- (fru_data + sizeof(struct fru_multirec_header));
- #if WORDS_BIGENDIAN
- ps->capacity = BSWAP_16(ps->capacity);
- ps->peak_va = BSWAP_16(ps->peak_va);
- ps->lowend_input1 = BSWAP_16(ps->lowend_input1);
- ps->highend_input1 = BSWAP_16(ps->highend_input1);
- ps->lowend_input2 = BSWAP_16(ps->lowend_input2);
- ps->highend_input2 = BSWAP_16(ps->highend_input2);
- ps->combined_capacity = BSWAP_16(ps->combined_capacity);
- ps->peak_cap_ht = BSWAP_16(ps->peak_cap_ht);
- #endif
- peak_hold_up_time = (ps->peak_cap_ht & 0xf000) >> 12;
- peak_capacity = ps->peak_cap_ht & 0x0fff;
- printf (" Power Supply Record\n");
- printf (" Capacity : %d W\n",
- ps->capacity);
- printf (" Peak VA : %d VA\n",
- ps->peak_va);
- printf (" Inrush Current : %d A\n",
- ps->inrush_current);
- printf (" Inrush Interval : %d ms\n",
- ps->inrush_interval);
- printf (" Input Voltage Range 1 : %d-%d V\n",
- ps->lowend_input1 / 100, ps->highend_input1 / 100);
- printf (" Input Voltage Range 2 : %d-%d V\n",
- ps->lowend_input2 / 100, ps->highend_input2 / 100);
- printf (" Input Frequency Range : %d-%d Hz\n",
- ps->lowend_freq, ps->highend_freq);
- printf (" A/C Dropout Tolerance : %d ms\n",
- ps->dropout_tolerance);
- printf (" Flags : %s%s%s%s%s\n",
- ps->predictive_fail ? "'Predictive fail' " : "",
- ps->pfc ? "'Power factor correction' " : "",
- ps->autoswitch ? "'Autoswitch voltage' " : "",
- ps->hotswap ? "'Hot swap' " : "",
- ps->predictive_fail ? ps->rps_threshold ?
- ps->tach ? "'Two pulses per rotation'" : "'One pulse per rotation'" :
- ps->tach ? "'Failure on pin de-assertion'" : "'Failure on pin assertion'" : "");
- printf (" Peak capacity : %d W\n",
- peak_capacity);
- printf (" Peak capacity holdup : %d s\n",
- peak_hold_up_time);
- if (ps->combined_capacity == 0)
- printf (" Combined capacity : not specified\n");
- else
- printf (" Combined capacity : %d W (%s and %s)\n",
- ps->combined_capacity,
- combined_voltage_desc [ps->combined_voltage1],
- combined_voltage_desc [ps->combined_voltage2]);
- if (ps->predictive_fail)
- printf (" Fan lower threshold : %d RPS\n",
- ps->rps_threshold);
- break;
- case FRU_RECORD_TYPE_DC_OUTPUT:
- dc = (struct fru_multirec_dcoutput *)
- (fru_data + sizeof(struct fru_multirec_header));
- #if WORDS_BIGENDIAN
- dc->nominal_voltage = BSWAP_16(dc->nominal_voltage);
- dc->max_neg_dev = BSWAP_16(dc->max_neg_dev);
- dc->max_pos_dev = BSWAP_16(dc->max_pos_dev);
- dc->ripple_and_noise = BSWAP_16(dc->ripple_and_noise);
- dc->min_current = BSWAP_16(dc->min_current);
- dc->max_current = BSWAP_16(dc->max_current);
- #endif
- printf (" DC Output Record\n");
- printf (" Output Number : %d\n",
- dc->output_number);
- printf (" Standby power : %s\n",
- dc->standby ? "Yes" : "No");
- printf (" Nominal voltage : %.2f V\n",
- (double) dc->nominal_voltage / 100);
- printf (" Max negative deviation : %.2f V\n",
- (double) dc->max_neg_dev / 100);
- printf (" Max positive deviation : %.2f V\n",
- (double) dc->max_pos_dev / 100);
- printf (" Ripple and noise pk-pk : %d mV\n",
- dc->ripple_and_noise);
- printf (" Minimum current draw : %.3f A\n",
- (double) dc->min_current / 1000);
- printf (" Maximum current draw : %.3f A\n",
- (double) dc->max_current / 1000);
- break;
- case FRU_RECORD_TYPE_DC_LOAD:
- dl = (struct fru_multirec_dcload *)
- (fru_data + sizeof(struct fru_multirec_header));
- #if WORDS_BIGENDIAN
- dl->nominal_voltage = BSWAP_16(dl->nominal_voltage);
- dl->min_voltage = BSWAP_16(dl->min_voltage);
- dl->max_voltage = BSWAP_16(dl->max_voltage);
- dl->ripple_and_noise = BSWAP_16(dl->ripple_and_noise);
- dl->min_current = BSWAP_16(dl->min_current);
- dl->max_current = BSWAP_16(dl->max_current);
- #endif
- printf (" DC Load Record\n");
- printf (" Output Number : %d\n",
- dl->output_number);
- printf (" Nominal voltage : %.2f V\n",
- (double) dl->nominal_voltage / 100);
- printf (" Min voltage allowed : %.2f V\n",
- (double) dl->min_voltage / 100);
- printf (" Max voltage allowed : %.2f V\n",
- (double) dl->max_voltage / 100);
- printf (" Ripple and noise pk-pk : %d mV\n",
- dl->ripple_and_noise);
- printf (" Minimum current load : %.3f A\n",
- (double) dl->min_current / 1000);
- printf (" Maximum current load : %.3f A\n",
- (double) dl->max_current / 1000);
- break;
- case FRU_RECORD_TYPE_OEM_EXTENSION:
- {
- struct fru_multirec_oem_header *oh=(struct fru_multirec_oem_header *)
- &fru_data[sizeof(struct fru_multirec_header)];
- uint32_t iana = oh->mfg_id[0] | oh->mfg_id[1]<<8 | oh->mfg_id[2]<<16;
- /* Now makes sure this is really PICMG record */
- if( iana == IPMI_OEM_PICMG ){
- printf(" PICMG Extension Record\n");
- ipmi_fru_picmg_ext_print(fru_data,
- sizeof(struct fru_multirec_header),
- h->len);
- }
- /* FIXME: Add OEM record support here */
- else{
- printf(" OEM (%s) Record\n", val2str( iana, ipmi_oem_info));
- }
- }
- break;
- }
- } while (!(h->format & 0x80));
- lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)", last_off, last_off);
- free(fru_data);
- }
- /* ipmi_fru_query_new_value - Query new values to replace original FRU content
- *
- * @data: FRU data
- * @offset: offset of the bytes to be modified in data
- * @len: size of the modified data
- *
- * returns : TRUE if data changed
- * returns : FALSE if data not changed
- */
- int ipmi_fru_query_new_value(uint8_t *data,int offset, size_t len)
- {
- int status=FALSE;
- int ret;
- char answer;
- printf("Would you like to change this value <y/n> ? ");
- ret = scanf("%c", &answer);
- if (ret != 1) {
- return FALSE;
- }
- if( answer == 'y' || answer == 'Y' ){
- int i;
- unsigned int *holder;
- holder = malloc(len);
- printf(
- "Enter hex values for each of the %d entries (lsb first), "
- "hit <enter> between entries\n", (int)len);
- /* I can't assign scanf' %x into a single char */
- for( i=0;i<len;i++ ){
- ret = scanf("%x", holder+i);
- if (ret != 1) {
- free(holder);
- return FALSE;
- }
- }
- for( i=0;i<len;i++ ){
- data[offset++] = (unsigned char) *(holder+i);
- }
- /* &data[offset++] */
- free(holder);
- holder = NULL;
- status = TRUE;
- }
- else{
- printf("Entered %c\n",answer);
- }
- return status;
- }
- /* ipmi_fru_oemkontron_edit -
- * Query new values to replace original FRU content
- * This is a generic enough to support any type of 'OEM' record
- * because the user supplies 'IANA number' , 'record Id' and 'record' version'
- *
- * However, the parser must have 'apriori' knowledge of the record format
- * The currently supported record is :
- *
- * IANA : 15000 (Kontron)
- * RECORD ID : 3
- * RECORD VERSION: 0 (or 1)
- *
- * I would have like to put that stuff in an OEM specific file, but apart for
- * the record format information, all commands are really standard 'FRU' command
- *
- *
- * @data: FRU data
- * @offset: start of the current multi record (start of header)
- * @len: len of the current record (excluding header)
- * @h: pointer to record header
- * @oh: pointer to OEM /PICMG header
- *
- * returns: TRUE if data changed
- * returns: FALSE if data not changed
- */
- #define OEM_KONTRON_INFORMATION_RECORD 3
- #define EDIT_OEM_KONTRON_COMPLETE_ARG_COUNT 12
- #define GET_OEM_KONTRON_COMPLETE_ARG_COUNT 5
- /*
- ./src/ipmitool fru edit 0
- oem 15000 3 0 name instance FIELD1 FIELD2 FIELD3 crc32
- */
- #define OEM_KONTRON_SUBCOMMAND_ARG_POS 2
- #define OEM_KONTRON_IANA_ARG_POS 3
- #define OEM_KONTRON_RECORDID_ARG_POS 4
- #define OEM_KONTRON_FORMAT_ARG_POS 5
- #define OEM_KONTRON_NAME_ARG_POS 6
- #define OEM_KONTRON_INSTANCE_ARG_POS 7
- #define OEM_KONTRON_VERSION_ARG_POS 8
- #define OEM_KONTRON_BUILDDATE_ARG_POS 9
- #define OEM_KONTRON_UPDATEDATE_ARG_POS 10
- #define OEM_KONTRON_CRC32_ARG_POS 11
- #define OEM_KONTRON_FIELD_SIZE 8
- #define OEM_KONTRON_VERSION_FIELD_SIZE 10
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(1)
- #endif
- typedef struct OemKontronInformationRecordV0{
- uint8_t field1TypeLength;
- uint8_t field1[OEM_KONTRON_FIELD_SIZE];
- uint8_t field2TypeLength;
- uint8_t field2[OEM_KONTRON_FIELD_SIZE];
- uint8_t field3TypeLength;
- uint8_t field3[OEM_KONTRON_FIELD_SIZE];
- uint8_t crcTypeLength;
- uint8_t crc32[OEM_KONTRON_FIELD_SIZE];
- }tOemKontronInformationRecordV0;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(0)
- #endif
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(1)
- #endif
- typedef struct OemKontronInformationRecordV1{
- uint8_t field1TypeLength;
- uint8_t field1[OEM_KONTRON_VERSION_FIELD_SIZE];
- uint8_t field2TypeLength;
- uint8_t field2[OEM_KONTRON_FIELD_SIZE];
- uint8_t field3TypeLength;
- uint8_t field3[OEM_KONTRON_FIELD_SIZE];
- uint8_t crcTypeLength;
- uint8_t crc32[OEM_KONTRON_FIELD_SIZE];
- }tOemKontronInformationRecordV1;
- #ifdef HAVE_PRAGMA_PACK
- #pragma pack(0)
- #endif
- /*
- ./src/ipmitool fru get 0 oem iana 3
- */
- static void ipmi_fru_oemkontron_get( int argc, char ** argv,uint8_t * fru_data,
- int off,int len,
- struct fru_multirec_header *h,
- struct fru_multirec_oem_header *oh)
- {
- static int badParams=FALSE;
- int start = off;
- int offset = start;
- offset += sizeof(struct fru_multirec_oem_header);
- if(!badParams){
- /* the 'OEM' field is already checked in caller */
- if( argc > OEM_KONTRON_SUBCOMMAND_ARG_POS ){
- if(strncmp("oem", argv[OEM_KONTRON_SUBCOMMAND_ARG_POS],3)){
- printf("usage: fru get <id> <oem>\n");
- badParams = TRUE;
- return;
- }
- }
- if( argc<GET_OEM_KONTRON_COMPLETE_ARG_COUNT ){
- printf("usage: oem <iana> <recordid>\n");
- printf("usage: oem 15000 3\n");
- badParams = TRUE;
- return;
- }
- }
- if(!badParams){
- if(oh->record_id == OEM_KONTRON_INFORMATION_RECORD ) {
- uint8_t version;
- printf("Kontron OEM Information Record\n");
- version = oh->record_version;
- uint8_t blockCount;
- uint8_t blockIndex=0;
- unsigned int matchInstance = 0;
- uint8_t instance = 0;
-
- if (str2uchar(argv[OEM_KONTRON_INSTANCE_ARG_POS], &instance) != 0) {
- lprintf(LOG_ERR,
- "Instance argument '%s' is either invalid or out of range.",
- argv[OEM_KONTRON_INSTANCE_ARG_POS]);
- badParams = TRUE;
- return;
- }
- blockCount = fru_data[offset++];
- for(blockIndex=0;blockIndex<blockCount;blockIndex++){
- void * pRecordData;
- uint8_t nameLen;
- nameLen = ( fru_data[offset++] &= 0x3F );
- printf(" Name: %*.*s\n",nameLen, nameLen, (const char *)(fru_data+offset));
- offset+=nameLen;
- pRecordData = &fru_data[offset];
- printf(" Record Version: %d\n", version);
- if( version == 0 )
- {
- printf(" Version: %*.*s\n",
- OEM_KONTRON_FIELD_SIZE,
- OEM_KONTRON_FIELD_SIZE,
- ((tOemKontronInformationRecordV0 *) pRecordData)->field1);
- printf(" Build Date: %*.*s\n",
- OEM_KONTRON_FIELD_SIZE,
- OEM_KONTRON_FIELD_SIZE,
- ((tOemKontronInformationRecordV0 *) pRecordData)->field2);
- printf(" Update Date: %*.*s\n",
- OEM_KONTRON_FIELD_SIZE,
- OEM_KONTRON_FIELD_SIZE,
- ((tOemKontronInformationRecordV0 *) pRecordData)->field3);
- printf(" Checksum: %*.*s\n\n",
- OEM_KONTRON_FIELD_SIZE,
- OEM_KONTRON_FIELD_SIZE,
- ((tOemKontronInformationRecordV0 *) pRecordData)->crc32);
- matchInstance++;
- offset+= sizeof(tOemKontronInformationRecordV0);
- offset++;
- }
- else if ( version == 1 )
- {
- printf(" Version: %*.*s\n",
- OEM_KONTRON_VERSION_FIELD_SIZE,
- OEM_KONTRON_VERSION_FIELD_SIZE,
- ((tOemKontronInformationRecordV1 *) pRecordData)->field1);
- printf(" Build Date: %*.*s\n",
- OEM_KONTRON_FIELD_SIZE,
- OEM_KONTRON_FIELD_SIZE,
- ((tOemKontronInformationRecordV1 *) pRecordData)->field2);
- printf(" Update Date: %*.*s\n",
- OEM_KONTRON_FIELD_SIZE,
- OEM_KONTRON_FIELD_SIZE,
- ((tOemKontronInformationRecordV1 *) pRecordData)->field3);
- printf(" Checksum: %*.*s\n\n",
- OEM_KONTRON_FIELD_SIZE,
- OEM_KONTRON_FIELD_SIZE,
- ((tOemKontronInformationRecordV1 *) pRecordData)->crc32);
- matchInstance++;
- offset+= sizeof(tOemKontronInformationRecordV1);
- offset++;
- }
- else
- {
- printf (" Unsupported version %d\n",version);
- }
- }
- }
- }
- }
- static int ipmi_fru_oemkontron_edit( int argc, char ** argv,uint8_t * fru_data,
- int off,int len,
- struct fru_multirec_header *h,
- struct fru_multirec_oem_header *oh)
- {
- static int badParams=FALSE;
- int hasChanged = FALSE;
- int start = off;
- int offset = start;
- int length = len;
- int i;
- uint8_t record_id = 0;
- offset += sizeof(struct fru_multirec_oem_header);
- if(!badParams){
- /* the 'OEM' field is already checked in caller */
- if( argc > OEM_KONTRON_SUBCOMMAND_ARG_POS ){
- if(strncmp("oem", argv[OEM_KONTRON_SUBCOMMAND_ARG_POS],3)){
- printf("usage: fru edit <id> <oem> <args...>\n");
- badParams = TRUE;
- return hasChanged;
- }
- }
- if( argc<EDIT_OEM_KONTRON_COMPLETE_ARG_COUNT ){
- printf("usage: oem <iana> <recordid> <format> <args...>\n");
- printf("usage: oem 15000 3 0 <name> <instance> <field1>"\
- " <field2> <field3> <crc32>\n");
- badParams = TRUE;
- return hasChanged;
- }
- if (str2uchar(argv[OEM_KONTRON_RECORDID_ARG_POS], &record_id) != 0) {
- lprintf(LOG_ERR,
- "Record ID argument '%s' is either invalid or out of range.",
- argv[OEM_KONTRON_RECORDID_ARG_POS]);
- badParams = TRUE;
- return hasChanged;
- }
- if (record_id == OEM_KONTRON_INFORMATION_RECORD) {
- for(i=OEM_KONTRON_VERSION_ARG_POS;i<=OEM_KONTRON_CRC32_ARG_POS;i++){
- if( (strlen(argv[i]) != OEM_KONTRON_FIELD_SIZE) &&
- (strlen(argv[i]) != OEM_KONTRON_VERSION_FIELD_SIZE)) {
- printf("error: version fields must have %d characters\n",
- OEM_KONTRON_FIELD_SIZE);
- badParams = TRUE;
- return hasChanged;
- }
- }
- }
- }
- if(!badParams){
- if(oh->record_id == OEM_KONTRON_INFORMATION_RECORD ) {
- uint8_t formatVersion = 0;
- uint8_t version;
- if (str2uchar(argv[OEM_KONTRON_FORMAT_ARG_POS], &formatVersion) != 0) {
- lprintf(LOG_ERR,
- "Format argument '%s' is either invalid or out of range.",
- argv[OEM_KONTRON_FORMAT_ARG_POS]);
- badParams = TRUE;
- return hasChanged;
- }
- printf(" Kontron OEM Information Record\n");
- version = oh->record_version;
- if( version == formatVersion ){
- uint8_t blockCount;
- uint8_t blockIndex=0;
- uint8_t matchInstance = 0;
- uint8_t instance = 0;
-
- if (str2uchar(argv[OEM_KONTRON_INSTANCE_ARG_POS], &instance) != 0) {
- lprintf(LOG_ERR,
- "Instance argument '%s' is either invalid or out of range.",
- argv[OEM_KONTRON_INSTANCE_ARG_POS]);
- badParams = TRUE;
- return hasChanged;
- }
- blockCount = fru_data[offset++];
- printf(" blockCount: %d\n",blockCount);
- for(blockIndex=0;blockIndex<blockCount;blockIndex++){
- void * pRecordData;
- uint8_t nameLen;
- nameLen = ( fru_data[offset++] & 0x3F );
- if( version == 0 || version == 1 )
- {
- if(!strncmp((char *)argv[OEM_KONTRON_NAME_ARG_POS],
- (const char *)(fru_data+offset),nameLen)&& (matchInstance == instance)){
- printf ("Found : %s\n",argv[OEM_KONTRON_NAME_ARG_POS]);
- offset+=nameLen;
- pRecordData = &fru_data[offset];
- if( version == 0 )
- {
- memcpy( ((tOemKontronInformationRecordV0 *)
- pRecordData)->field1 ,
- argv[OEM_KONTRON_VERSION_ARG_POS] ,
- OEM_KONTRON_FIELD_SIZE);
- memcpy( ((tOemKontronInformationRecordV0 *)
- pRecordData)->field2 ,
- argv[OEM_KONTRON_BUILDDATE_ARG_POS],
- OEM_KONTRON_FIELD_SIZE);
- memcpy( ((tOemKontronInformationRecordV0 *)
- pRecordData)->field3 ,
- argv[OEM_KONTRON_UPDATEDATE_ARG_POS],
- OEM_KONTRON_FIELD_SIZE);
- memcpy( ((tOemKontronInformationRecordV0 *)
- pRecordData)->crc32 ,
- argv[OEM_KONTRON_CRC32_ARG_POS] ,
- OEM_KONTRON_FIELD_SIZE);
- }
- else
- {
- memcpy( ((tOemKontronInformationRecordV1 *)
- pRecordData)->field1 ,
- argv[OEM_KONTRON_VERSION_ARG_POS] ,
- OEM_KONTRON_VERSION_FIELD_SIZE);
- memcpy( ((tOemKontronInformationRecordV1 *)
- pRecordData)->field2 ,
- argv[OEM_KONTRON_BUILDDATE_ARG_POS],
- OEM_KONTRON_FIELD_SIZE);
- memcpy( ((tOemKontronInformationRecordV1 *)
- pRecordData)->field3 ,
- argv[OEM_KONTRON_UPDATEDATE_ARG_POS],
- OEM_KONTRON_FIELD_SIZE);
- memcpy( ((tOemKontronInformationRecordV1 *)
- pRecordData)->crc32 ,
- argv[OEM_KONTRON_CRC32_ARG_POS] ,
- OEM_KONTRON_FIELD_SIZE);
- }
- matchInstance++;
- hasChanged = TRUE;
- }
- else if(!strncmp((char *)argv[OEM_KONTRON_NAME_ARG_POS],
- (const char *)(fru_data+offset), nameLen)){
- printf ("Skipped : %s [instance %d]\n",argv[OEM_KONTRON_NAME_ARG_POS],
- (unsigned int)matchInstance);
- matchInstance++;
- offset+=nameLen;
- }
- else {
- offset+=nameLen;
- }
- if( version == 0 )
- {
- offset+= sizeof(tOemKontronInformationRecordV0);
- }
- else
- {
- offset+= sizeof(tOemKontronInformationRecordV1);
- }
- offset++;
- }
- else
- {
- printf (" Unsupported version %d\n",version);
- }
- }
- }
- else{
- printf(" Version: %d\n",version);
- }
- }
- if( hasChanged ){
- uint8_t record_checksum =0;
- uint8_t header_checksum =0;
- int index;
- lprintf(LOG_DEBUG,"Initial record checksum : %x",h->record_checksum);
- lprintf(LOG_DEBUG,"Initial header checksum : %x",h->header_checksum);
- for(index=0;index<length;index++){
- record_checksum+= fru_data[start+index];
- }
- /* Update Record checksum */
- h->record_checksum = ~record_checksum + 1;
- for(index=0;index<(sizeof(struct fru_multirec_header) -1);index++){
- uint8_t data= *( (uint8_t *)h+ index);
- header_checksum+=data;
- }
- /* Update header checksum */
- h->header_checksum = ~header_checksum + 1;
- lprintf(LOG_DEBUG,"Final record checksum : %x",h->record_checksum);
- lprintf(LOG_DEBUG,"Final header checksum : %x",h->header_checksum);
- /* write back data */
- }
- }
- return hasChanged;
- }
- /* ipmi_fru_picmg_ext_edit - Query new values to replace original FRU content
- *
- * @data: FRU data
- * @offset: start of the current multi record (start of header)
- * @len: len of the current record (excluding header)
- * @h: pointer to record header
- * @oh: pointer to OEM /PICMG header
- *
- * returns: TRUE if data changed
- * returns: FALSE if data not changed
- */
- static int ipmi_fru_picmg_ext_edit(uint8_t * fru_data,
- int off,int len,
- struct fru_multirec_header *h,
- struct fru_multirec_oem_header *oh)
- {
- int hasChanged = FALSE;
- int start = off;
- int offset = start;
- int length = len;
- offset += sizeof(struct fru_multirec_oem_header);
- switch (oh->record_id)
- {
- case FRU_AMC_ACTIVATION:
- printf(" FRU_AMC_ACTIVATION\n");
- {
- int index=offset;
- uint16_t max_current;
- max_current = fru_data[offset];
- max_current |= fru_data[++offset]<<8;
- printf(" Maximum Internal Current(@12V): %.2f A (0x%02x)\n",
- (float)max_current / 10.0f, max_current);
- if( ipmi_fru_query_new_value(fru_data,index,2) ){
- max_current = fru_data[index];
- max_current |= fru_data[++index]<<8;
- printf(" New Maximum Internal Current(@12V): %.2f A (0x%02x)\n",
- (float)max_current / 10.0f, max_current);
- hasChanged = TRUE;
- }
- printf(" Module Activation Readiness: %i sec.\n", fru_data[++offset]);
- printf(" Descriptor Count: %i\n", fru_data[++offset]);
- printf("\n");
- for (++offset;
- offset < (off + length);
- offset += sizeof(struct fru_picmgext_activation_record)) {
- struct fru_picmgext_activation_record * a =
- (struct fru_picmgext_activation_record *) &fru_data[offset];
- printf(" IPMB-Address: 0x%x\n", a->ibmb_addr);
- printf(" Max. Module Current: %.2f A\n", (float)a->max_module_curr / 10.0f);
- printf("\n");
- }
- }
- break;
- case FRU_AMC_CURRENT:
- printf(" FRU_AMC_CURRENT\n");
- {
- int index=offset;
- unsigned char current;
- current = fru_data[index];
- printf(" Current draw(@12V): %.2f A (0x%02x)\n",
- (float)current / 10.0f, current);
- if( ipmi_fru_query_new_value(fru_data, index, 1) ){
- current = fru_data[index];
- printf(" New Current draw(@12V): %.2f A (0x%02x)\n",
- (float)current / 10.0f, current);
- hasChanged = TRUE;
- }
- }
- break;
- }
- if( hasChanged ){
- uint8_t record_checksum =0;
- uint8_t header_checksum =0;
- int index;
- lprintf(LOG_DEBUG,"Initial record checksum : %x",h->record_checksum);
- lprintf(LOG_DEBUG,"Initial header checksum : %x",h->header_checksum);
- for(index=0;index<length;index++){
- record_checksum+= fru_data[start+index];
- }
- /* Update Record checksum */
- h->record_checksum = ~record_checksum + 1;
- for(index=0;index<(sizeof(struct fru_multirec_header) -1);index++){
- uint8_t data= *( (uint8_t *)h+ index);
- header_checksum+=data;
- }
- /* Update header checksum */
- h->header_checksum = ~header_checksum + 1;
- lprintf(LOG_DEBUG,"Final record checksum : %x",h->record_checksum);
- lprintf(LOG_DEBUG,"Final header checksum : %x",h->header_checksum);
- /* write back data */
- }
- return hasChanged;
- }
- /* ipmi_fru_picmg_ext_print - prints OEM fru record (PICMG)
- *
- * @fru_data: FRU data
- * @offset: offset of the bytes to be modified in data
- * @length: size of the record
- *
- * returns : n/a
- */
- static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length)
- {
- struct fru_multirec_oem_header *h;
- int guid_count;
- int offset = off;
- int start_offset = off;
- int i;
- h = (struct fru_multirec_oem_header *) &fru_data[offset];
- offset += sizeof(struct fru_multirec_oem_header);
- switch (h->record_id)
- {
- case FRU_PICMG_BACKPLANE_P2P:
- {
- uint8_t index;
- unsigned int data;
- struct fru_picmgext_slot_desc *slot_d;
- slot_d =
- (struct fru_picmgext_slot_desc*)&fru_data[offset];
- offset += sizeof(struct fru_picmgext_slot_desc);
- printf(" FRU_PICMG_BACKPLANE_P2P\n");
- while (offset <= (start_offset+length)) {
- printf("\n");
- printf(" Channel Type: ");
- switch (slot_d->chan_type)
- {
- case 0x00:
- case 0x07:
- printf("PICMG 2.9\n");
- break;
- case 0x08:
- printf("Single Port Fabric IF\n");
- break;
- case 0x09:
- printf("Double Port Fabric IF\n");
- break;
- case 0x0a:
- printf("Full Channel Fabric IF\n");
- break;
- case 0x0b:
- printf("Base IF\n");
- break;
- case 0x0c:
- printf("Update Channel IF\n");
- break;
- case 0x0d:
- printf("ShMC Cross Connect\n");
- break;
- default:
- printf("Unknown IF (0x%x)\n",
- slot_d->chan_type);
- break;
- }
- printf(" Slot Addr. : %02x\n",
- slot_d->slot_addr );
- printf(" Channel Count: %i\n",
- slot_d->chn_count);
- for (index = 0;
- index < (slot_d->chn_count);
- index++) {
- struct fru_picmgext_chn_desc *d;
- data = (fru_data[offset+0]) |
- (fru_data[offset+1] << 8) |
- (fru_data[offset+2] << 16);
- d = (struct fru_picmgext_chn_desc *)&data;
- if (verbose) {
- printf( " "
- "Chn: %02x -> "
- "Chn: %02x in "
- "Slot: %02x\n",
- d->local_chn,
- d->remote_chn,
- d->remote_slot);
- }
- offset += FRU_PICMGEXT_CHN_DESC_RECORD_SIZE;
- }
- slot_d = (struct fru_picmgext_slot_desc*)&fru_data[offset];
- offset += sizeof(struct fru_picmgext_slot_desc);
- }
- }
- break;
- case FRU_PICMG_ADDRESS_TABLE:
- {
- unsigned int hwaddr;
- unsigned int sitetype;
- unsigned int sitenum;
- unsigned int entries;
- unsigned int i;
- char *picmg_site_type_strings[] = {
- "AdvancedTCA Board",
- "Power Entry",
- "Shelf FRU Information",
- "Dedicated ShMC",
- "Fan Tray",
- "Fan Filter Tray",
- "Alarm",
- "AdvancedMC Module",
- "PMC",
- "Rear Transition Module"};
- printf(" FRU_PICMG_ADDRESS_TABLE\n");
- printf(" Type/Len: 0x%02x\n", fru_data[offset++]);
- printf(" Shelf Addr: ");
- for (i=0;i<20;i++) {
- printf("0x%02x ", fru_data[offset++]);
- }
- printf("\n");
- entries = fru_data[offset++];
- printf(" Addr Table Entries: 0x%02x\n", entries);
- for (i=0; i<entries; i++) {
- hwaddr = fru_data[offset];
- sitenum = fru_data[offset + 1];
- sitetype = fru_data[offset + 2];
- printf(
- " HWAddr: 0x%02x (0x%02x) SiteNum: %d SiteType: 0x%02x %s\n",
- hwaddr, hwaddr * 2,
- sitenum, sitetype,
- (sitetype < 0xa) ?
- picmg_site_type_strings[sitetype] :
- "Reserved");
- offset += 3;
- }
- }
- break;
- case FRU_PICMG_SHELF_POWER_DIST:
- {
- unsigned int entries;
- unsigned int feeds;
- unsigned int hwaddr;
- unsigned int i;
- unsigned int id;
- unsigned int j;
- unsigned int maxext;
- unsigned int maxint;
- unsigned int minexp;
- printf(" FRU_PICMG_SHELF_POWER_DIST\n");
- feeds = fru_data[offset++];
- printf(" Number of Power Feeds: 0x%02x\n",
- feeds);
- for (i=0; i<feeds; i++) {
- printf(" Feed %d:\n", i);
- maxext = fru_data[offset] |
- (fru_data[offset+1] << 8);
- offset += 2;
- maxint = fru_data[offset] |
- (fru_data[offset+1] << 8);
- offset += 2;
- minexp = fru_data[offset];
- offset += 1;
- entries = fru_data[offset];
- offset += 1;
- printf(
- " Max External Current: %d.%d Amps (0x%04x)\n",
- maxext / 10, maxext % 10, maxext);
- if (maxint < 0xffff) {
- printf(
- " Max Internal Current: %d.%d Amps (0x%04x)\n",
- maxint / 10, maxint % 10,
- maxint);
- } else {
- printf(
- " Max Internal Current: Not Specified\n");
- }
- if (minexp >= 0x48 && minexp <= 0x90) {
- printf(
- " Min Expected Voltage: -%02d.%dV\n",
- minexp / 2, (minexp % 2) * 5);
- } else {
- printf(
- " Min Expected Voltage: -%dV (actual invalid value 0x%x)\n",
- 36, minexp);
- }
- for (j=0; j < entries; j++) {
- hwaddr = fru_data[offset++];
- id = fru_data[offset++];
- printf(
- " FRU HW Addr: 0x%02x (0x%02x)",
- hwaddr, hwaddr * 2);
- printf(
- " FRU ID: 0x%02x\n",
- id);
- }
- }
- }
- break;
- case FRU_PICMG_SHELF_ACTIVATION:
- {
- unsigned int i;
- unsigned int count = 0;
- printf(" FRU_PICMG_SHELF_ACTIVATION\n");
- printf(
- " Allowance for FRU Act Readiness: 0x%02x\n",
- fru_data[offset++]);
- count = fru_data[offset++];
- printf(
- " FRU activation and Power Desc Cnt: 0x%02x\n",
- count);
- for (i=0; i<count; i++) {
- printf(" HW Addr: 0x%02x ",
- fru_data[offset++]);
- printf(" FRU ID: 0x%02x ",
- fru_data[offset++]);
- printf(" Max FRU Power: 0x%04x ",
- fru_data[offset+0] |
- (fru_data[offset+1]<<8));
- offset += 2;
- printf(" Config: 0x%02x \n",
- fru_data[offset++]);
- }
- }
- break;
- case FRU_PICMG_SHMC_IP_CONN:
- printf(" FRU_PICMG_SHMC_IP_CONN\n");
- break;
- case FRU_PICMG_BOARD_P2P:
- printf(" FRU_PICMG_BOARD_P2P\n");
- guid_count = fru_data[offset++];
- printf(" GUID count: %2d\n", guid_count);
- for (i = 0 ; i < guid_count; i++ ) {
- int j;
- printf(" GUID [%2d]: 0x", i);
- for (j=0; j < sizeof(struct fru_picmgext_guid);
- j++) {
- printf("%02x", fru_data[offset+j]);
- }
- printf("\n");
- offset += sizeof(struct fru_picmgext_guid);
- }
- printf("\n");
- for (; offset < off + length;
- offset += sizeof(struct fru_picmgext_link_desc)) {
- /* to solve little endian /big endian problem */
- struct fru_picmgext_link_desc *d;
- unsigned int data = (fru_data[offset+0]) |
- (fru_data[offset+1] << 8) |
- (fru_data[offset+2] << 16) |
- (fru_data[offset+3] << 24);
- d = (struct fru_picmgext_link_desc *) &data;
- printf(" Link Grouping ID: 0x%02x\n",
- d->grouping);
- printf(" Link Type Extension: 0x%02x - ",
- d->ext);
- if (d->type == FRU_PICMGEXT_LINK_TYPE_BASE) {
- switch (d->ext) {
- case 0:
- printf("10/100/1000BASE-T Link (four-pair)\n");
- break;
- case 1:
- printf("ShMC Cross-connect (two-pair)\n");
- break;
- default:
- printf("Unknown\n");
- break;
- }
- } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET) {
- switch (d->ext) {
- case 0:
- printf("1000Base-BX\n");
- break;
- case 1:
- printf("10GBase-BX4 [XAUI]\n");
- break;
- case 2:
- printf("FC-PI\n");
- break;
- case 3:
- printf("1000Base-KX\n");
- break;
- case 4:
- printf("10GBase-KX4\n");
- break;
- default:
- printf("Unknown\n");
- break;
- }
- } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD) {
- switch (d->ext) {
- case 0:
- printf("10GBase-KR\n");
- break;
- case 1:
- printf("40GBase-KR4\n");
- break;
- default:
- printf("Unknown\n");
- break;
- }
- } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND) {
- printf("Unknown\n");
- } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR) {
- printf("Unknown\n");
- } else if (d->type == FRU_PICMGEXT_LINK_TYPE_PCIE) {
- printf("Unknown\n");
- } else {
- printf("Unknown\n");
- }
- printf(" Link Type: 0x%02x - ",
- d->type);
- switch (d->type) {
- case FRU_PICMGEXT_LINK_TYPE_BASE:
- printf("PICMG 3.0 Base Interface 10/100/1000\n");
- break;
- case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET:
- printf("PICMG 3.1 Ethernet Fabric Interface\n");
- printf(" Base signaling Link Class\n");
- break;
- case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND:
- printf("PICMG 3.2 Infiniband Fabric Interface\n");
- break;
- case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR:
- printf("PICMG 3.3 Star Fabric Interface\n");
- break;
- case FRU_PICMGEXT_LINK_TYPE_PCIE:
- printf("PICMG 3.4 PCI Express Fabric Interface\n");
- break;
- case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD:
- printf("PICMG 3.1 Ethernet Fabric Interface\n");
- printf(" 10.3125Gbd signaling Link Class\n");
- break;
- default:
- if (d->type == 0 || d->type == 0xff) {
- printf("Reserved\n");
- } else if (d->type >= 0x06 && d->type <= 0xef) {
- printf("Reserved\n");
- } else if (d->type >= 0xf0 && d->type <= 0xfe) {
- printf("OEM GUID Definition\n");
- } else {
- printf("Invalid\n");
- }
- break;
- }
- printf(" Link Designator: \n");
- printf(" Port Flag: 0x%02x\n",
- d->desig_port);
- printf(" Interface: 0x%02x - ",
- d->desig_if);
- switch (d->desig_if) {
- case FRU_PICMGEXT_DESIGN_IF_BASE:
- printf("Base Interface\n");
- break;
- case FRU_PICMGEXT_DESIGN_IF_FABRIC:
- printf("Fabric Interface\n");
- break;
- case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL:
- printf("Update Channel\n");
- break;
- case FRU_PICMGEXT_DESIGN_IF_RESERVED:
- printf("Reserved\n");
- break;
- default:
- printf("Invalid");
- break;
- }
- printf(" Channel Number: 0x%02x\n",
- d->desig_channel);
- printf("\n");
- }
- break;
- case FRU_AMC_CURRENT:
- {
- unsigned char current;
- printf(" FRU_AMC_CURRENT\n");
- current = fru_data[offset];
- printf(" Current draw(@12V): %.2f A [ %.2f Watt ]\n",
- (float)current / 10.0f,
- (float)current / 10.0f * 12.0f);
- printf("\n");
- }
- break;
- case FRU_AMC_ACTIVATION:
- printf(" FRU_AMC_ACTIVATION\n");
- {
- uint16_t max_current;
- max_current = fru_data[offset];
- max_current |= fru_data[++offset]<<8;
- printf(" Maximum Internal Current(@12V): %.2f A [ %.2f Watt ]\n",
- (float)max_current / 10.0f,
- (float)max_current / 10.0f * 12.0f);
- printf(" Module Activation Readiness: %i sec.\n", fru_data[++offset]);
- printf(" Descriptor Count: %i\n", fru_data[++offset]);
- printf("\n");
- for(++offset; offset < off + length;
- offset += sizeof(struct fru_picmgext_activation_record))
- {
- struct fru_picmgext_activation_record *a;
- a = (struct fru_picmgext_activation_record *)&fru_data[offset];
- printf(" IPMB-Address: 0x%x\n",
- a->ibmb_addr);
- printf(" Max. Module Current: %.2f A\n",
- (float)a->max_module_curr / 10.0f);
- printf("\n");
- }
- }
- break;
- case FRU_AMC_CARRIER_P2P:
- {
- uint16_t index;
- printf(" FRU_CARRIER_P2P\n");
- for(; offset < off + length; ) {
- struct fru_picmgext_carrier_p2p_record * h =
- (struct fru_picmgext_carrier_p2p_record *)&fru_data[offset];
- printf("\n");
- printf(" Resource ID: %i",
- (h->resource_id & 0x07));
- printf(" Type: ");
- if ((h->resource_id>>7) == 1) {
- printf("AMC\n");
- } else {
- printf("Local\n");
- }
- printf(" Descriptor Count: %i\n",
- h->p2p_count);
- offset += sizeof(struct fru_picmgext_carrier_p2p_record);
- for (index = 0; index < h->p2p_count; index++) {
- /* to solve little endian /big endian problem */
- unsigned char data[3];
- struct fru_picmgext_carrier_p2p_descriptor * desc;
- # ifndef WORDS_BIGENDIAN
- data[0] = fru_data[offset+0];
- data[1] = fru_data[offset+1];
- data[2] = fru_data[offset+2];
- # else
- data[0] = fru_data[offset+2];
- data[1] = fru_data[offset+1];
- data[2] = fru_data[offset+0];
- # endif
- desc = (struct fru_picmgext_carrier_p2p_descriptor*)&data;
- printf(" Port: %02d\t-> Remote Port: %02d\t",
- desc->local_port, desc->remote_port);
- if ((desc->remote_resource_id >> 7) == 1) {
- printf("[ AMC ID: %02d ]\n",
- desc->remote_resource_id & 0x0F);
- } else {
- printf("[ local ID: %02d ]\n",
- desc->remote_resource_id & 0x0F);
- }
- offset += sizeof(struct fru_picmgext_carrier_p2p_descriptor);
- }
- }
- }
- break;
- case FRU_AMC_P2P:
- {
- unsigned int index;
- unsigned char channel_count;
- struct fru_picmgext_amc_p2p_record * h;
- printf(" FRU_AMC_P2P\n");
- guid_count = fru_data[offset];
- printf(" GUID count: %2d\n", guid_count);
- for (i = 0 ; i < guid_count; i++) {
- int j;
- printf(" GUID %2d: ", i);
- for (j=0; j < sizeof(struct fru_picmgext_guid);
- j++) {
- printf("%02x", fru_data[offset+j]);
- offset += sizeof(struct fru_picmgext_guid);
- printf("\n");
- }
- h = (struct fru_picmgext_amc_p2p_record *)&fru_data[++offset];
- printf(" %s",
- (h->record_type ?
- "AMC Module:" : "On-Carrier Device"));
- printf(" Resource ID: %i\n", h->resource_id);
- offset += sizeof(struct fru_picmgext_amc_p2p_record);
- channel_count = fru_data[offset++];
- printf(" Descriptor Count: %i\n",
- channel_count);
- for (index = 0; index < channel_count; index++) {
- unsigned int data;
- struct fru_picmgext_amc_channel_desc_record *d;
- /* pack the data in little endian format.
- * Stupid intel...
- */
- data = fru_data[offset] |
- (fru_data[offset + 1] << 8) |
- (fru_data[offset + 2] << 16);
- d = (struct fru_picmgext_amc_channel_desc_record *)&data;
- printf(" Lane 0 Port: %i\n",
- d->lane0port);
- printf(" Lane 1 Port: %i\n",
- d->lane1port);
- printf(" Lane 2 Port: %i\n",
- d->lane2port);
- printf(" Lane 3 Port: %i\n\n",
- d->lane3port);
- offset += FRU_PICMGEXT_AMC_CHANNEL_DESC_RECORD_SIZE;
- }
- for (; offset < off + length;) {
- unsigned int data[2];
- struct fru_picmgext_amc_link_desc_record *l;
- l = (struct fru_picmgext_amc_link_desc_record *)&data[0];
- data[0] = fru_data[offset] |
- (fru_data[offset + 1] << 8) |
- (fru_data[offset + 2] << 16) |
- (fru_data[offset + 3] << 24);
- data[1] = fru_data[offset + 4];
- printf( " Link Designator: Channel ID: %i\n"
- " Port Flag 0: %s%s%s%s\n",
- l->channel_id,
- (l->port_flag_0)?"o":"-",
- (l->port_flag_1)?"o":"-",
- (l->port_flag_2)?"o":"-",
- (l->port_flag_3)?"o":"-" );
- switch (l->type) {
- case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE:
- /* AMC.1 */
- printf( " Link Type: %02x - "
- "AMC.1 PCI Express\n", l->type);
- switch (l->type_ext) {
- case AMC_LINK_TYPE_EXT_PCIE_G1_NSSC:
- printf( " Link Type Ext: %i - "
- " Gen 1 capable - non SSC\n",
- l->type_ext);
- break;
- case AMC_LINK_TYPE_EXT_PCIE_G1_SSC:
- printf( " Link Type Ext: %i - "
- " Gen 1 capable - SSC\n",
- l->type_ext);
- break;
- case AMC_LINK_TYPE_EXT_PCIE_G2_NSSC:
- printf( " Link Type Ext: %i - "
- " Gen 2 capable - non SSC\n",
- l->type_ext);
- break;
- case AMC_LINK_TYPE_EXT_PCIE_G2_SSC:
- printf( " Link Type Ext: %i - "
- " Gen 2 capable - SSC\n",
- l->type_ext);
- break;
- default:
- printf( " Link Type Ext: %i - "
- " Invalid\n",
- l->type_ext);
- break;
- }
- break;
- case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1:
- case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2:
- /* AMC.1 */
- printf( " Link Type: %02x - "
- "AMC.1 PCI Express Advanced Switching\n",
- l->type);
- printf(" Link Type Ext: %i\n",
- l->type_ext);
- break;
- case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET:
- /* AMC.2 */
- printf( " Link Type: %02x - "
- "AMC.2 Ethernet\n",
- l->type);
- switch (l->type_ext) {
- case AMC_LINK_TYPE_EXT_ETH_1000_BX:
- printf( " Link Type Ext: %i - "
- " 1000Base-Bx (SerDES Gigabit) Ethernet Link\n",
- l->type_ext);
- break;
- case AMC_LINK_TYPE_EXT_ETH_10G_XAUI:
- printf( " Link Type Ext: %i - "
- " 10Gbit XAUI Ethernet Link\n",
- l->type_ext);
- break;
- default:
- printf( " Link Type Ext: %i - "
- " Invalid\n",
- l->type_ext);
- break;
- }
- break;
- case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE:
- /* AMC.3 */
- printf( " Link Type: %02x - "
- "AMC.3 Storage\n",
- l->type);
- switch (l->type_ext) {
- case AMC_LINK_TYPE_EXT_STORAGE_FC:
- printf( " Link Type Ext: %i - "
- " Fibre Channel\n",
- l->type_ext);
- break;
- case AMC_LINK_TYPE_EXT_STORAGE_SATA:
- printf( " Link Type Ext: %i - "
- " Serial ATA\n",
- l->type_ext);
- break;
- case AMC_LINK_TYPE_EXT_STORAGE_SAS:
- printf( " Link Type Ext: %i - "
- " Serial Attached SCSI\n",
- l->type_ext);
- break;
- default:
- printf( " Link Type Ext: %i - "
- " Invalid\n",
- l->type_ext);
- break;
- }
- break;
- case FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO:
- /* AMC.4 */
- printf( " Link Type: %02x - "
- "AMC.4 Serial Rapid IO\n",
- l->type);
- printf(" Link Type Ext: %i\n",
- l->type_ext);
- break;
- default:
- printf( " Link Type: %02x - "
- "reserved or OEM GUID",
- l->type);
- printf(" Link Type Ext: %i\n",
- l->type_ext);
- break;
- }
- printf(" Link group Id: %i\n",
- l->group_id);
- printf(" Link Asym Match: %i\n\n",
- l->asym_match);
- offset += FRU_PICMGEXT_AMC_LINK_DESC_RECORD_SIZE;
- }
- }
- }
- break;
- case FRU_AMC_CARRIER_INFO:
- {
- unsigned char extVersion;
- unsigned char siteCount;
- printf(" FRU_CARRIER_INFO\n");
- extVersion = fru_data[offset++];
- siteCount = fru_data[offset++];
- printf(" AMC.0 extension version: R%d.%d\n",
- (extVersion >> 0)& 0x0F,
- (extVersion >> 4)& 0x0F );
- printf(" Carrier Sie Number Cnt: %d\n", siteCount);
- for (i = 0 ; i < siteCount; i++ ){
- printf(" Site ID: %i \n", fru_data[offset++]);
- }
- printf("\n");
- }
- break;
- case FRU_PICMG_CLK_CARRIER_P2P:
- {
- unsigned char desc_count;
- int i,j;
- printf(" FRU_PICMG_CLK_CARRIER_P2P\n");
- desc_count = fru_data[offset++];
- for(i=0; i<desc_count; i++){
- unsigned char resource_id;
- unsigned char channel_count;
- resource_id = fru_data[offset++];
- channel_count = fru_data[offset++];
- printf("\n");
- printf(" Clock Resource ID: 0x%02x Type: ", resource_id);
- if((resource_id & 0xC0)>>6 == 0) {printf("On-Carrier-Device\n");}
- else if((resource_id & 0xC0)>>6 == 1) {printf("AMC slot\n");}
- else if((resource_id & 0xC0)>>6 == 2) {printf("Backplane\n");}
- else{ printf("reserved\n");}
- printf(" Channel Count: 0x%02x\n", channel_count);
- for(j=0; j<channel_count; j++){
- unsigned char loc_channel, rem_channel, rem_resource;
- loc_channel = fru_data[offset++];
- rem_channel = fru_data[offset++];
- rem_resource = fru_data[offset++];
- printf(" CLK-ID: 0x%02x ->", loc_channel);
- printf(" remote CLKID: 0x%02x ", rem_channel);
- if((rem_resource & 0xC0)>>6 == 0) {printf("[ Carrier-Dev");}
- else if((rem_resource & 0xC0)>>6 == 1) {printf("[ AMC slot ");}
- else if((rem_resource & 0xC0)>>6 == 2) {printf("[ Backplane ");}
- else{ printf("reserved ");}
- printf(" 0x%02x ]\n", rem_resource&0xF);
- }
- }
- printf("\n");
- }
- break;
- case FRU_PICMG_CLK_CONFIG:
- {
- unsigned char resource_id, descr_count;
- int i,j;
- printf(" FRU_PICMG_CLK_CONFIG\n");
- resource_id = fru_data[offset++];
- descr_count = fru_data[offset++];
- printf("\n");
- printf(" Clock Resource ID: 0x%02x\n", resource_id);
- printf(" Descr. Count: 0x%02x\n", descr_count);
- for(i=0; i<descr_count; i++){
- unsigned char channel_id, control;
- unsigned char indirect_cnt, direct_cnt;
- channel_id = fru_data[offset++];
- control = fru_data[offset++];
- printf(" CLK-ID: 0x%02x - ", channel_id);
- printf("CTRL 0x%02x [ %12s ]\n",
- control,
- ((control&0x1)==0)?"Carrier IPMC":"Application");
- indirect_cnt = fru_data[offset++];
- direct_cnt = fru_data[offset++];
- printf(" Cnt: Indirect 0x%02x / Direct 0x%02x\n",
- indirect_cnt,
- direct_cnt);
- /* indirect desc */
- for(j=0; j<indirect_cnt; j++){
- unsigned char feature;
- unsigned char dep_chn_id;
- feature = fru_data[offset++];
- dep_chn_id = fru_data[offset++];
- printf(" Feature: 0x%02x [%8s] - ", feature, (feature&0x1)==1?"Source":"Receiver");
- printf(" Dep. CLK-ID: 0x%02x\n", dep_chn_id);
- }
- /* direct desc */
- for(j=0; j<direct_cnt; j++){
- unsigned char feature, family, accuracy;
- unsigned int freq, min_freq, max_freq;
- feature = fru_data[offset++];
- family = fru_data[offset++];
- accuracy = fru_data[offset++];
- freq = (fru_data[offset+0] << 0 ) | (fru_data[offset+1] << 8 )
- | (fru_data[offset+2] << 16) | (fru_data[offset+3] << 24);
- offset += 4;
- min_freq = (fru_data[offset+0] << 0 ) | (fru_data[offset+1] << 8 )
- | (fru_data[offset+2] << 16) | (fru_data[offset+3] << 24);
- offset += 4;
- max_freq = (fru_data[offset+0] << 0 ) | (fru_data[offset+1] << 8 )
- | (fru_data[offset+2] << 16) | (fru_data[offset+3] << 24);
- offset += 4;
- printf(" - Feature: 0x%02x - PLL: %x / Asym: %s\n",
- feature,
- (feature > 1) & 1,
- (feature&1)?"Source":"Receiver");
- printf(" Family: 0x%02x - AccLVL: 0x%02x\n", family, accuracy);
- printf(" FRQ: %-9ld - min: %-9ld - max: %-9ld\n",
- freq, min_freq, max_freq);
- }
- printf("\n");
- }
- printf("\n");
- }
- break;
- case FRU_UTCA_FRU_INFO_TABLE:
- case FRU_UTCA_CARRIER_MNG_IP:
- case FRU_UTCA_CARRIER_INFO:
- case FRU_UTCA_CARRIER_LOCATION:
- case FRU_UTCA_SHMC_IP_LINK:
- case FRU_UTCA_POWER_POLICY:
- case FRU_UTCA_ACTIVATION:
- case FRU_UTCA_PM_CAPABILTY:
- case FRU_UTCA_FAN_GEOGRAPHY:
- case FRU_UTCA_CLOCK_MAPPING:
- case FRU_UTCA_MSG_BRIDGE_POLICY:
- case FRU_UTCA_OEM_MODULE_DESC:
- printf(" Not implemented yet. uTCA specific record found!!\n");
- printf(" - Record ID: 0x%02x\n", h->record_id);
- break;
- default:
- printf(" Unknown OEM Extension Record ID: %x\n", h->record_id);
- break;
- }
- }
- /* __ipmi_fru_print - Do actual work to print a FRU by its ID
- *
- * @intf: ipmi interface
- * @id: fru id
- *
- * returns -1 on error
- * returns 0 if successful
- * returns 1 if device not present
- */
- static int
- __ipmi_fru_print(struct ipmi_intf * intf, uint8_t id)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- struct fru_info fru;
- struct fru_header header;
- uint8_t msg_data[4];
- memset(&fru, 0, sizeof(struct fru_info));
- memset(&header, 0, sizeof(struct fru_header));
- /*
- * get info about this FRU
- */
- memset(msg_data, 0, 4);
- msg_data[0] = id;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf(" Device not present (No Response)\n");
- return -1;
- }
- if (rsp->ccode > 0) {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- return -1;
- }
- memset(&fru, 0, sizeof(fru));
- fru.size = (rsp->data[1] << 8) | rsp->data[0];
- fru.access = rsp->data[2] & 0x1;
- lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
- fru.size, fru.access ? "words" : "bytes");
- if (fru.size < 1) {
- lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
- return -1;
- }
- /*
- * retrieve the FRU header
- */
- msg_data[0] = id;
- msg_data[1] = 0;
- msg_data[2] = 0;
- msg_data[3] = 8;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_DATA;
- req.msg.data = msg_data;
- req.msg.data_len = 4;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf(" Device not present (No Response)\n");
- return 1;
- }
- if (rsp->ccode > 0) {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- return 1;
- }
- if (verbose > 1)
- printbuf(rsp->data, rsp->data_len, "FRU DATA");
- memcpy(&header, rsp->data + 1, 8);
- if (header.version != 1) {
- lprintf(LOG_ERR, " Unknown FRU header version 0x%02x",
- header.version);
- return -1;
- }
- /* offsets need converted to bytes
- * but that conversion is not done to the structure
- * because we may end up with offset > 255
- * which would overflow our 1-byte offset field */
- lprintf(LOG_DEBUG, "fru.header.version: 0x%x",
- header.version);
- lprintf(LOG_DEBUG, "fru.header.offset.internal: 0x%x",
- header.offset.internal * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.chassis: 0x%x",
- header.offset.chassis * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.board: 0x%x",
- header.offset.board * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.product: 0x%x",
- header.offset.product * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.multi: 0x%x",
- header.offset.multi * 8);
- /*
- * rather than reading the entire part
- * only read the areas we'll format
- */
- /* chassis area */
- if ((header.offset.chassis*8) >= sizeof(struct fru_header))
- fru_area_print_chassis(intf, &fru, id, header.offset.chassis*8);
- /* board area */
- if ((header.offset.board*8) >= sizeof(struct fru_header))
- fru_area_print_board(intf, &fru, id, header.offset.board*8);
- /* product area */
- if ((header.offset.product*8) >= sizeof(struct fru_header))
- fru_area_print_product(intf, &fru, id, header.offset.product*8);
- /* multirecord area */
- if( verbose==0 ) /* scipp parsing multirecord */
- return 0;
- if ((header.offset.multi*8) >= sizeof(struct fru_header))
- fru_area_print_multirec(intf, &fru, id, header.offset.multi*8);
- return 0;
- }
- /* ipmi_fru_print - Print a FRU from its SDR locator record
- *
- * @intf: ipmi interface
- * @fru: SDR FRU Locator Record
- *
- * returns -1 on error
- */
- int
- ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
- {
- char desc[17];
- uint8_t bridged_request = 0;
- uint32_t save_addr;
- uint32_t save_channel;
- int rc = 0;
- if (fru == NULL)
- return __ipmi_fru_print(intf, 0);
- /* Logical FRU Device
- * dev_type == 0x10
- * modifier
- * 0x00 = IPMI FRU Inventory
- * 0x01 = DIMM Memory ID
- * 0x02 = IPMI FRU Inventory
- * 0x03 = System Processor FRU
- * 0xff = unspecified
- *
- * EEPROM 24C01 or equivalent
- * dev_type >= 0x08 && dev_type <= 0x0f
- * modifier
- * 0x00 = unspecified
- * 0x01 = DIMM Memory ID
- * 0x02 = IPMI FRU Inventory
- * 0x03 = System Processor Cartridge
- */
- if (fru->dev_type != 0x10 &&
- (fru->dev_type_modifier != 0x02 ||
- fru->dev_type < 0x08 || fru->dev_type > 0x0f))
- return -1;
- if (fru->dev_slave_addr == IPMI_BMC_SLAVE_ADDR &&
- fru->device_id == 0)
- return 0;
- memset(desc, 0, sizeof(desc));
- memcpy(desc, fru->id_string, fru->id_code & 0x01f);
- desc[fru->id_code & 0x01f] = 0;
- printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
- switch (fru->dev_type_modifier) {
- case 0x00:
- case 0x02:
- if (BRIDGE_TO_SENSOR(intf, fru->dev_slave_addr,
- fru->channel_num)) {
- bridged_request = 1;
- save_addr = intf->target_addr;
- intf->target_addr = fru->dev_slave_addr;
- save_channel = intf->target_channel;
- intf->target_channel = fru->channel_num;
- }
- /* print FRU */
- rc = __ipmi_fru_print(intf, fru->device_id);
- if (bridged_request) {
- intf->target_addr = save_addr;
- intf->target_channel = save_channel;
- }
- break;
- case 0x01:
- rc = ipmi_spd_print_fru(intf, fru->device_id);
- break;
- default:
- if (verbose)
- printf(" Unsupported device 0x%02x "
- "type 0x%02x with modifier 0x%02x\n",
- fru->device_id, fru->dev_type,
- fru->dev_type_modifier);
- else
- printf(" Unsupported device\n");
- }
- printf("\n");
- return rc;
- }
- /* ipmi_fru_print_all - Print builtin FRU + SDR FRU Locator records
- *
- * @intf: ipmi interface
- *
- * returns -1 on error
- */
- static int
- ipmi_fru_print_all(struct ipmi_intf * intf)
- {
- struct ipmi_sdr_iterator * itr;
- struct sdr_get_rs * header;
- struct sdr_record_fru_locator * fru;
- int rc;
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- struct ipm_devid_rsp *devid;
- struct sdr_record_mc_locator * mc;
- uint32_t save_addr;
- printf("FRU Device Description : Builtin FRU Device (ID 0)\n");
- /* TODO: Figure out if FRU device 0 may show up in SDR records. */
- /* Do a Get Device ID command to determine device support */
- memset (&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_APP;
- req.msg.cmd = BMC_GET_DEVICE_ID;
- req.msg.data_len = 0;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Get Device ID command failed");
- return -1;
- }
- if (rsp->ccode > 0) {
- lprintf(LOG_ERR, "Get Device ID command failed: %s",
- val2str(rsp->ccode, completion_code_vals));
- return -1;
- }
- devid = (struct ipm_devid_rsp *) rsp->data;
- /* Check the FRU inventory device bit to decide whether various */
- /* FRU commands can be issued to FRU device #0 LUN 0 */
- if (devid->adtl_device_support & 0x08) { /* FRU Inventory Device bit? */
- rc = ipmi_fru_print(intf, NULL);
- printf("\n");
- }
- if ((itr = ipmi_sdr_start(intf, 0)) == NULL)
- return -1;
- /* Walk the SDRs looking for FRU Devices and Management Controller Devices. */
- /* For FRU devices, print the FRU from the SDR locator record. */
- /* For MC devices, issue FRU commands to the satellite controller to print */
- /* FRU data. */
- while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL)
- {
- if (header->type == SDR_RECORD_TYPE_MC_DEVICE_LOCATOR ) {
- /* Check the capabilities of the Management Controller Device */
- mc = (struct sdr_record_mc_locator *)
- ipmi_sdr_get_record(intf, header, itr);
- /* Does this MC device support FRU inventory device? */
- if (mc && (mc->dev_support & 0x08) && /* FRU inventory device? */
- intf->target_addr != mc->dev_slave_addr) {
- /* Yes. Prepare to issue FRU commands to FRU device #0 LUN 0 */
- /* using the slave address specified in the MC record. */
- /* save current target address */
- save_addr = intf->target_addr;
- /* set new target address to satellite controller */
- intf->target_addr = mc->dev_slave_addr;
- printf("FRU Device Description : %-16s\n", mc->id_string);
- /* print the FRU by issuing FRU commands to the satellite */
- /* controller. */
- rc = __ipmi_fru_print(intf, 0);
- printf("\n");
- /* restore previous target */
- intf->target_addr = save_addr;
- }
- if (mc) {
- free(mc);
- mc = NULL;
- }
- continue;
- }
- if (header->type != SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR)
- continue;
- /* Print the FRU from the SDR locator record. */
- fru = (struct sdr_record_fru_locator *)
- ipmi_sdr_get_record(intf, header, itr);
- if (fru == NULL || !fru->logical) {
- if (fru) {
- free(fru);
- fru = NULL;
- }
- continue;
- }
- rc = ipmi_fru_print(intf, fru);
- free(fru);
- fru = NULL;
- }
- ipmi_sdr_end(intf, itr);
- return rc;
- }
- /* ipmi_fru_read_help() - print help text for 'read'
- *
- * returns void
- */
- void
- ipmi_fru_read_help()
- {
- lprintf(LOG_NOTICE, "fru read <fru id> <fru file>");
- lprintf(LOG_NOTICE, "Note: FRU ID and file(incl. full path) must be specified.");
- lprintf(LOG_NOTICE, "Example: ipmitool fru read 0 /root/fru.bin");
- } /* ipmi_fru_read_help() */
- static void
- ipmi_fru_read_to_bin(struct ipmi_intf * intf,
- char * pFileName,
- uint8_t fruId)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- struct fru_info fru;
- uint8_t msg_data[4];
- uint8_t * pFruBuf;
- msg_data[0] = fruId;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (!rsp)
- return;
- if (rsp->ccode > 0) {
- if (rsp->ccode == 0xc3)
- printf (" Timeout accessing FRU info. (Device not present?)\n");
- return;
- }
- memset(&fru, 0, sizeof(fru));
- fru.size = (rsp->data[1] << 8) | rsp->data[0];
- fru.access = rsp->data[2] & 0x1;
- if (verbose) {
- printf("Fru Size = %d bytes\n",fru.size);
- printf("Fru Access = %xh\n", fru.access);
- }
- pFruBuf = malloc(fru.size);
- if (pFruBuf != NULL) {
- printf("Fru Size : %d bytes\n",fru.size);
- read_fru_area(intf, &fru, fruId, 0, fru.size, pFruBuf);
- } else {
- lprintf(LOG_ERR, "Cannot allocate %d bytes\n", fru.size);
- return;
- }
- if(pFruBuf != NULL)
- {
- FILE * pFile;
- pFile = fopen(pFileName,"wb");
- if (pFile) {
- fwrite(pFruBuf, fru.size, 1, pFile);
- printf("Done\n");
- } else {
- lprintf(LOG_ERR, "Error opening file %s\n", pFileName);
- free(pFruBuf);
- pFruBuf = NULL;
- return;
- }
- fclose(pFile);
- }
- free(pFruBuf);
- pFruBuf = NULL;
- }
- static void
- ipmi_fru_write_from_bin(struct ipmi_intf * intf,
- char * pFileName,
- uint8_t fruId)
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- struct fru_info fru;
- uint8_t msg_data[4];
- uint8_t *pFruBuf;
- uint16_t len = 0;
- FILE *pFile;
- msg_data[0] = fruId;
- memset(&req, 0, sizeof (req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (!rsp)
- return;
- if (rsp->ccode) {
- if (rsp->ccode == 0xc3)
- printf(" Timeout accessing FRU info. (Device not present?)\n");
- return;
- }
- memset(&fru, 0, sizeof(fru));
- fru.size = (rsp->data[1] << 8) | rsp->data[0];
- fru.access = rsp->data[2] & 0x1;
- if (verbose) {
- printf("Fru Size = %d bytes\n", fru.size);
- printf("Fru Access = %xh\n", fru.access);
- }
- pFruBuf = malloc(fru.size);
- if (pFruBuf == NULL) {
- lprintf(LOG_ERR, "Cannot allocate %d bytes\n", fru.size);
- return;
- }
- pFile = fopen(pFileName, "rb");
- if (pFile != NULL) {
- len = fread(pFruBuf, 1, fru.size, pFile);
- printf("Fru Size : %d bytes\n", fru.size);
- printf("Size to Write : %d bytes\n", len);
- fclose(pFile);
- } else {
- lprintf(LOG_ERR, "Error opening file %s\n", pFileName);
- }
- if (len != 0) {
- write_fru_area(intf, &fru, fruId,0, 0, len, pFruBuf);
- lprintf(LOG_INFO,"Done");
- }
- free(pFruBuf);
- pFruBuf = NULL;
- }
- /* ipmi_fru_write_help() - print help text for 'write'
- *
- * retruns void
- */
- void
- ipmi_fru_write_help()
- {
- lprintf(LOG_NOTICE, "fru write <fru id> <fru file>");
- lprintf(LOG_NOTICE, "Note: FRU ID and file(incl. full path) must be specified.");
- lprintf(LOG_NOTICE, "Example: ipmitool fru write 0 /root/fru.bin");
- } /* ipmi_fru_write_help() */
- /* ipmi_fru_edit_help - print help text for 'fru edit' command
- *
- * returns void
- */
- void
- ipmi_fru_edit_help()
- {
- lprintf(LOG_NOTICE,
- "fru edit <fruid> field <section> <index> <string> - edit FRU string");
- lprintf(LOG_NOTICE,
- "fru edit <fruid> oem iana <record> <format> <args> - limited OEM support");
- } /* ipmi_fru_edit_help() */
- /* ipmi_fru_edit_multirec - Query new values to replace original FRU content
- *
- * @intf: interface to use
- * @id: FRU id to work on
- *
- * returns: nothing
- */
- /* Work in progress, copy paste most of the stuff for other functions in this
- file ... not elegant yet */
- static int
- ipmi_fru_edit_multirec(struct ipmi_intf * intf, uint8_t id ,
- int argc, char ** argv)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- struct fru_info fru;
- struct fru_header header;
- uint8_t msg_data[4];
- uint16_t retStatus = 0;
- uint32_t offFruMultiRec;
- uint32_t fruMultiRecSize = 0;
- struct fru_info fruInfo;
- retStatus = ipmi_fru_get_multirec_location_from_fru(intf, id, &fruInfo,
- &offFruMultiRec,
- &fruMultiRecSize);
- if (retStatus != 0) {
- return retStatus;
- }
- lprintf(LOG_DEBUG, "FRU Size : %lu\n", fruMultiRecSize);
- lprintf(LOG_DEBUG, "Multi Rec offset: %lu\n", offFruMultiRec);
- {
- memset(&fru, 0, sizeof(struct fru_info));
- memset(&header, 0, sizeof(struct fru_header));
- /*
- * get info about this FRU
- */
- memset(msg_data, 0, 4);
- msg_data[0] = id;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf(" Device not present (No Response)\n");
- return -1;
- }
- if (rsp->ccode > 0) {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- return -1;
- }
- memset(&fru, 0, sizeof(fru));
- fru.size = (rsp->data[1] << 8) | rsp->data[0];
- fru.access = rsp->data[2] & 0x1;
- lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
- fru.size, fru.access ? "words" : "bytes");
- if (fru.size < 1) {
- lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
- return -1;
- }
- }
- {
- uint8_t * fru_data;
- uint32_t i;
- uint32_t offset= offFruMultiRec;
- struct fru_multirec_header * h;
- uint32_t last_off, len;
- uint8_t error=0;
- i = last_off = offset;
- memset(&fru, 0, sizeof(fru));
- fru_data = malloc(fru.size + 1);
- if (fru_data == NULL) {
- lprintf(LOG_ERR, " Out of memory!");
- return -1;
- }
- memset(fru_data, 0, fru.size + 1);
- do {
- h = (struct fru_multirec_header *) (fru_data + i);
- /* read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time */
- if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
- {
- len = fru.size - last_off;
- if (len > FRU_MULTIREC_CHUNK_SIZE)
- len = FRU_MULTIREC_CHUNK_SIZE;
- if (read_fru_area(intf, &fru, id, last_off, len, fru_data) < 0)
- break;
- last_off += len;
- }
- if( h->type == FRU_RECORD_TYPE_OEM_EXTENSION ){
- struct fru_multirec_oem_header *oh=(struct fru_multirec_oem_header *)
- &fru_data[i + sizeof(struct fru_multirec_header)];
- uint32_t iana = oh->mfg_id[0] | oh->mfg_id[1]<<8 | oh->mfg_id[2]<<16;
- uint32_t suppliedIana = 0 ;
- /* Now makes sure this is really PICMG record */
- /* Default to PICMG for backward compatibility */
- if( argc <=2 ) {
- suppliedIana = IPMI_OEM_PICMG;
- } else {
- if( !strncmp( argv[2] , "oem" , 3 )) {
- /* Expect IANA number next */
- if( argc <= 3 ) {
- lprintf(LOG_ERR, "oem iana <record> <format> [<args>]");
- error = 1;
- } else {
- if (str2uint(argv[3], &suppliedIana) == 0) {
- lprintf(LOG_DEBUG,
- "using iana: %d",
- suppliedIana);
- } else {
- lprintf(LOG_ERR,
- "Given IANA '%s' is invalid.",
- argv[3]);
- error = 1;
- }
- }
- }
- }
- if( suppliedIana == iana ) {
- lprintf(LOG_DEBUG, "Matching record found" );
- if( iana == IPMI_OEM_PICMG ){
- if( ipmi_fru_picmg_ext_edit(fru_data,
- i + sizeof(struct fru_multirec_header),
- h->len, h, oh )){
- /* The fru changed */
- write_fru_area(intf,&fru,id, i,i,
- h->len+ sizeof(struct fru_multirec_header), fru_data);
- }
- }
- else if( iana == IPMI_OEM_KONTRON ) {
- if( ipmi_fru_oemkontron_edit( argc,argv,fru_data,
- i + sizeof(struct fru_multirec_header),
- h->len, h, oh )){
- /* The fru changed */
- write_fru_area(intf,&fru,id, i,i,
- h->len+ sizeof(struct fru_multirec_header), fru_data);
- }
- }
- /* FIXME: Add OEM record support here */
- else{
- printf(" OEM IANA (%s) Record not support in this mode\n",
- val2str( iana, ipmi_oem_info));
- error = 1;
- }
- }
- }
- i += h->len + sizeof (struct fru_multirec_header);
- } while (!(h->format & 0x80) && (error != 1));
- free(fru_data);
- fru_data = NULL;
- }
- return 0;
- }
- /* ipmi_fru_get_help - print help text for 'fru get'
- *
- * returns void
- */
- void
- ipmi_fru_get_help()
- {
- lprintf(LOG_NOTICE,
- "fru get <fruid> oem iana <record> <format> <args> - limited OEM support");
- } /* ipmi_fru_get_help() */
- void
- ipmi_fru_internaluse_help()
- {
- lprintf(LOG_NOTICE,
- "fru internaluse <fru id> info - get internal use area size");
- lprintf(LOG_NOTICE,
- "fru internaluse <fru id> print - print internal use area in hex");
- lprintf(LOG_NOTICE,
- "fru internaluse <fru id> read <fru file> - read internal use area to file");
- lprintf(LOG_NOTICE,
- "fru internaluse <fru id> write <fru file> - write internal use area from file");
- } /* void ipmi_fru_internaluse_help() */
- /* ipmi_fru_get_multirec - Query new values to replace original FRU content
- *
- * @intf: interface to use
- * @id: FRU id to work on
- *
- * returns: nothing
- */
- /* Work in progress, copy paste most of the stuff for other functions in this
- file ... not elegant yet */
- static int
- ipmi_fru_get_multirec(struct ipmi_intf * intf, uint8_t id ,
- int argc, char ** argv)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- struct fru_info fru;
- struct fru_header header;
- uint8_t msg_data[4];
- uint16_t retStatus = 0;
- uint32_t offFruMultiRec;
- uint32_t fruMultiRecSize = 0;
- struct fru_info fruInfo;
- retStatus = ipmi_fru_get_multirec_location_from_fru(intf, id, &fruInfo,
- &offFruMultiRec,
- &fruMultiRecSize);
- if (retStatus != 0) {
- return retStatus;
- }
- lprintf(LOG_DEBUG, "FRU Size : %lu\n", fruMultiRecSize);
- lprintf(LOG_DEBUG, "Multi Rec offset: %lu\n", offFruMultiRec);
- {
- memset(&fru, 0, sizeof(struct fru_info));
- memset(&header, 0, sizeof(struct fru_header));
- /*
- * get info about this FRU
- */
- memset(msg_data, 0, 4);
- msg_data[0] = id;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf(" Device not present (No Response)\n");
- return -1;
- }
- if (rsp->ccode > 0) {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- return -1;
- }
- memset(&fru, 0, sizeof(fru));
- fru.size = (rsp->data[1] << 8) | rsp->data[0];
- fru.access = rsp->data[2] & 0x1;
- lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
- fru.size, fru.access ? "words" : "bytes");
- if (fru.size < 1) {
- lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
- return -1;
- }
- }
- {
- uint8_t * fru_data;
- uint32_t i;
- uint32_t offset= offFruMultiRec;
- struct fru_multirec_header * h;
- uint32_t last_off, len;
- uint8_t error=0;
- i = last_off = offset;
- fru_data = malloc(fru.size + 1);
- if (fru_data == NULL) {
- lprintf(LOG_ERR, " Out of memory!");
- return -1;
- }
- memset(fru_data, 0, fru.size + 1);
- do {
- h = (struct fru_multirec_header *) (fru_data + i);
- /* read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time */
- if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
- {
- len = fru.size - last_off;
- if (len > FRU_MULTIREC_CHUNK_SIZE)
- len = FRU_MULTIREC_CHUNK_SIZE;
- if (read_fru_area(intf, &fru, id, last_off, len, fru_data) < 0)
- break;
- last_off += len;
- }
- if( h->type == FRU_RECORD_TYPE_OEM_EXTENSION ){
- struct fru_multirec_oem_header *oh=(struct fru_multirec_oem_header *)
- &fru_data[i + sizeof(struct fru_multirec_header)];
- uint32_t iana = oh->mfg_id[0] | oh->mfg_id[1]<<8 | oh->mfg_id[2]<<16;
- uint32_t suppliedIana = 0 ;
- /* Now makes sure this is really PICMG record */
- if( !strncmp( argv[2] , "oem" , 3 )) {
- /* Expect IANA number next */
- if( argc <= 3 ) {
- lprintf(LOG_ERR, "oem iana <record> <format>");
- error = 1;
- } else {
- if (str2uint(argv[3], &suppliedIana) == 0) {
- lprintf(LOG_DEBUG,
- "using iana: %d",
- suppliedIana);
- } else {
- lprintf(LOG_ERR,
- "Given IANA '%s' is invalid.",
- argv[3]);
- error = 1;
- }
- }
- }
- if( suppliedIana == iana ) {
- lprintf(LOG_DEBUG, "Matching record found" );
- if( iana == IPMI_OEM_KONTRON ) {
- ipmi_fru_oemkontron_get( argc,argv,fru_data,
- i + sizeof(struct fru_multirec_header),
- h->len, h, oh );
- }
- /* FIXME: Add OEM record support here */
- else{
- printf(" OEM IANA (%s) Record not supported in this mode\n",
- val2str( iana, ipmi_oem_info));
- error = 1;
- }
- }
- }
- i += h->len + sizeof (struct fru_multirec_header);
- } while (!(h->format & 0x80) && (error != 1));
- free(fru_data);
- fru_data = NULL;
- }
- return 0;
- }
- static int
- ipmi_fru_upg_ekeying(struct ipmi_intf * intf,
- char * pFileName,
- uint8_t fruId)
- {
- struct fru_info fruInfo = {0};
- uint8_t *buf = NULL;
- uint32_t offFruMultiRec = 0;
- uint32_t fruMultiRecSize = 0;
- uint32_t offFileMultiRec = 0;
- uint32_t fileMultiRecSize = 0;
- if (pFileName == NULL) {
- lprintf(LOG_ERR, "File expected, but none given.");
- return (-1);
- }
- if (ipmi_fru_get_multirec_location_from_fru(intf, fruId, &fruInfo,
- &offFruMultiRec, &fruMultiRecSize) != 0) {
- lprintf(LOG_ERR, "Failed to get multirec location from FRU.");
- return (-1);
- }
- lprintf(LOG_DEBUG, "FRU Size : %lu\n", fruMultiRecSize);
- lprintf(LOG_DEBUG, "Multi Rec offset: %lu\n", offFruMultiRec);
- if (ipmi_fru_get_multirec_size_from_file(pFileName, &fileMultiRecSize,
- &offFileMultiRec) != 0) {
- lprintf(LOG_ERR, "Failed to get multirec size from file '%s'.", pFileName);
- return (-1);
- }
- buf = malloc(fileMultiRecSize);
- if (buf == NULL) {
- lprintf(LOG_ERR, "ipmitool: malloc failure");
- return (-1);
- }
- if (ipmi_fru_get_multirec_from_file(pFileName, buf, fileMultiRecSize,
- offFileMultiRec) != 0) {
- lprintf(LOG_ERR, "Failed to get multirec from file '%s'.", pFileName);
- if (buf != NULL) {
- free(buf);
- buf = NULL;
- }
- return (-1);
- }
- if (ipmi_fru_get_adjust_size_from_buffer(buf, &fileMultiRecSize) != 0) {
- lprintf(LOG_ERR, "Failed to adjust size from buffer.");
- if (buf != NULL) {
- free(buf);
- buf = NULL;
- }
- return (-1);
- }
- if (write_fru_area(intf, &fruInfo, fruId, 0, offFruMultiRec,
- fileMultiRecSize, buf) != 0) {
- lprintf(LOG_ERR, "Failed to write FRU area.");
- if (buf != NULL) {
- free(buf);
- buf = NULL;
- }
- return (-1);
- }
- if (buf != NULL) {
- free(buf);
- buf = NULL;
- }
- lprintf(LOG_INFO, "Done upgrading Ekey.");
- return 0;
- }
- /* ipmi_fru_upgekey_help - print help text for 'upgEkey'
- *
- * returns void
- */
- void
- ipmi_fru_upgekey_help()
- {
- lprintf(LOG_NOTICE, "fru upgEkey <fru id> <fru file>");
- lprintf(LOG_NOTICE, "Note: FRU ID and file(incl. full path) must be specified.");
- lprintf(LOG_NOTICE, "Example: ipmitool fru upgEkey 0 /root/fru.bin");
- } /* ipmi_fru_upgekey_help() */
- static int
- ipmi_fru_get_multirec_size_from_file(char * pFileName,
- uint32_t * pSize,
- uint32_t * pOffset)
- {
- struct fru_header header;
- FILE * pFile;
- uint8_t len = 0;
- uint32_t end = 0;
- *pSize = 0;
- pFile = fopen(pFileName,"rb");
- if (pFile) {
- rewind(pFile);
- len = fread(&header, 1, 8, pFile);
- fseek(pFile, 0, SEEK_END);
- end = ftell(pFile);
- fclose(pFile);
- }
- lprintf(LOG_DEBUG, "File Size = %lu\n", end);
- lprintf(LOG_DEBUG, "Len = %u\n", len);
- if (len != 8) {
- printf("Error with file %s in getting size\n", pFileName);
- return -1;
- }
- if (header.version != 0x01) {
- printf ("Unknown FRU header version %02x.\n", header.version);
- return -1;
- }
- /* Retreive length */
- if (((header.offset.internal * 8) > (header.offset.internal * 8)) &&
- ((header.offset.internal * 8) < end))
- end = (header.offset.internal * 8);
- if (((header.offset.chassis * 8) > (header.offset.chassis * 8)) &&
- ((header.offset.chassis * 8) < end))
- end = (header.offset.chassis * 8);
- if (((header.offset.board * 8) > (header.offset.board * 8)) &&
- ((header.offset.board * 8) < end))
- end = (header.offset.board * 8);
- if (((header.offset.product * 8) > (header.offset.product * 8)) &&
- ((header.offset.product * 8) < end))
- end = (header.offset.product * 8);
- *pSize = end - (header.offset.multi * 8);
- *pOffset = (header.offset.multi * 8);
- return 0;
- }
- int
- ipmi_fru_get_adjust_size_from_buffer(uint8_t * fru_data, uint32_t *pSize)
- {
- struct fru_multirec_header * head;
- int status = 0;
- uint8_t checksum = 0;
- uint8_t counter = 0;
- uint16_t count = 0;
- do {
- checksum = 0;
- head = (struct fru_multirec_header *) (fru_data + count);
- if (verbose) {
- printf("Adding (");
- }
- for (counter = 0; counter < sizeof(struct fru_multirec_header); counter++) {
- if (verbose) {
- printf(" %02X", *(fru_data + count + counter));
- }
- checksum += *(fru_data + count + counter);
- }
- if (verbose) {
- printf(")");
- }
- if (checksum != 0) {
- lprintf(LOG_ERR, "Bad checksum in Multi Records");
- status = (-1);
- if (verbose) {
- printf("--> FAIL");
- }
- } else if (verbose) {
- printf("--> OK");
- }
- if (verbose > 1 && checksum == 0) {
- for (counter = 0; counter < head->len; counter++) {
- printf(" %02X", *(fru_data + count + counter
- + sizeof(struct fru_multirec_header)));
- }
- }
- if (verbose) {
- printf("\n");
- }
- count += head->len + sizeof (struct fru_multirec_header);
- } while ((!(head->format & 0x80)) && (status == 0));
- *pSize = count;
- lprintf(LOG_DEBUG, "Size of multirec: %lu\n", *pSize);
- return status;
- }
- static int
- ipmi_fru_get_multirec_from_file(char * pFileName, uint8_t * pBufArea,
- uint32_t size, uint32_t offset)
- {
- FILE * pFile;
- uint32_t len = 0;
- if (pFileName == NULL) {
- lprintf(LOG_ERR, "Invalid file name given.");
- return (-1);
- }
-
- errno = 0;
- pFile = fopen(pFileName, "rb");
- if (!pFile) {
- lprintf(LOG_ERR, "Error opening file '%s': %i -> %s.", pFileName, errno,
- strerror(errno));
- return (-1);
- }
- errno = 0;
- if (fseek(pFile, offset, SEEK_SET) != 0) {
- lprintf(LOG_ERR, "Failed to seek in file '%s': %i -> %s.", pFileName, errno,
- strerror(errno));
- fclose(pFile);
- return (-1);
- }
- len = fread(pBufArea, size, 1, pFile);
- fclose(pFile);
- if (len != 1) {
- lprintf(LOG_ERR, "Error in file '%s'.", pFileName);
- return (-1);
- }
- return 0;
- }
- static int
- ipmi_fru_get_multirec_location_from_fru(struct ipmi_intf * intf,
- uint8_t fruId,
- struct fru_info *pFruInfo,
- uint32_t * pRetLocation,
- uint32_t * pRetSize)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- uint8_t msg_data[4];
- uint32_t end;
- struct fru_header header;
- *pRetLocation = 0;
- msg_data[0] = fruId;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (!rsp) {
- if (verbose > 1)
- printf("no response\n");
- return -1;
- }
- if (rsp->ccode > 0) {
- if (rsp->ccode == 0xc3)
- printf (" Timeout accessing FRU info. (Device not present?)\n");
- else
- printf (" CCODE = 0x%02x\n", rsp->ccode);
- return -1;
- }
- pFruInfo->size = (rsp->data[1] << 8) | rsp->data[0];
- pFruInfo->access = rsp->data[2] & 0x1;
- if (verbose > 1)
- printf("pFruInfo->size = %d bytes (accessed by %s)\n",
- pFruInfo->size, pFruInfo->access ? "words" : "bytes");
- if (!pFruInfo->size)
- return -1;
- msg_data[0] = fruId;
- msg_data[1] = 0;
- msg_data[2] = 0;
- msg_data[3] = 8;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_DATA;
- req.msg.data = msg_data;
- req.msg.data_len = 4;
- rsp = intf->sendrecv(intf, &req);
- if (!rsp)
- return -1;
- if (rsp->ccode > 0) {
- if (rsp->ccode == 0xc3)
- printf (" Timeout while reading FRU data. (Device not present?)\n");
- return -1;
- }
- if (verbose > 1)
- printbuf(rsp->data, rsp->data_len, "FRU DATA");
- memcpy(&header, rsp->data + 1, 8);
- if (header.version != 0x01) {
- printf (" Unknown FRU header version %02x.\n", header.version);
- return -1;
- }
- end = pFruInfo->size;
- /* Retreive length */
- if (((header.offset.internal * 8) > (header.offset.internal * 8)) &&
- ((header.offset.internal * 8) < end))
- end = (header.offset.internal * 8);
- if (((header.offset.chassis * 8) > (header.offset.chassis * 8)) &&
- ((header.offset.chassis * 8) < end))
- end = (header.offset.chassis * 8);
- if (((header.offset.board * 8) > (header.offset.board * 8)) &&
- ((header.offset.board * 8) < end))
- end = (header.offset.board * 8);
- if (((header.offset.product * 8) > (header.offset.product * 8)) &&
- ((header.offset.product * 8) < end))
- end = (header.offset.product * 8);
- *pRetSize = end;
- *pRetLocation = 8 * header.offset.multi;
- return 0;
- }
- /* ipmi_fru_get_internal_use_offset - Retreive internal use offset
- *
- * @intf: ipmi interface
- * @id: fru id
- *
- * returns -1 on error
- * returns 0 if successful
- * returns 1 if device not present
- */
- static int
- ipmi_fru_get_internal_use_info( struct ipmi_intf * intf,
- uint8_t id,
- struct fru_info * fru,
- uint16_t * size,
- uint16_t * offset)
- {
- struct ipmi_rs * rsp;
- struct ipmi_rq req;
- struct fru_header header;
- uint8_t msg_data[4];
- // Init output value
- * offset = 0;
- * size = 0;
- memset(fru, 0, sizeof(struct fru_info));
- memset(&header, 0, sizeof(struct fru_header));
- /*
- * get info about this FRU
- */
- memset(msg_data, 0, 4);
- msg_data[0] = id;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf(" Device not present (No Response)\n");
- return -1;
- }
- if (rsp->ccode > 0) {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- return -1;
- }
- memset(&fru, 0, sizeof(fru));
- fru->size = (rsp->data[1] << 8) | rsp->data[0];
- fru->access = rsp->data[2] & 0x1;
- lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
- fru->size, fru->access ? "words" : "bytes");
- if (fru->size < 1) {
- lprintf(LOG_ERR, " Invalid FRU size %d", fru->size);
- return -1;
- }
- /*
- * retrieve the FRU header
- */
- msg_data[0] = id;
- msg_data[1] = 0;
- msg_data[2] = 0;
- msg_data[3] = 8;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_DATA;
- req.msg.data = msg_data;
- req.msg.data_len = 4;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf(" Device not present (No Response)\n");
- return 1;
- }
- if (rsp->ccode > 0) {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- return 1;
- }
- if (verbose > 1)
- printbuf(rsp->data, rsp->data_len, "FRU DATA");
- memcpy(&header, rsp->data + 1, 8);
- if (header.version != 1) {
- lprintf(LOG_ERR, " Unknown FRU header version 0x%02x",
- header.version);
- return -1;
- }
- lprintf(LOG_DEBUG, "fru.header.version: 0x%x",
- header.version);
- lprintf(LOG_DEBUG, "fru.header.offset.internal: 0x%x",
- header.offset.internal * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.chassis: 0x%x",
- header.offset.chassis * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.board: 0x%x",
- header.offset.board * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.product: 0x%x",
- header.offset.product * 8);
- lprintf(LOG_DEBUG, "fru.header.offset.multi: 0x%x",
- header.offset.multi * 8);
- if((header.offset.internal*8) == 0)
- {
- * size = 0;
- * offset = 0;
- }
- else
- {
- (* offset) = (header.offset.internal*8);
- if(header.offset.chassis != 0)
- {
- (* size) = ((header.offset.chassis*8)-(* offset));
- }
- else if(header.offset.board != 0)
- {
- (* size) = ((header.offset.board*8)-(* offset));
- }
- else if(header.offset.product != 0)
- {
- (* size) = ((header.offset.product*8)-(* offset));
- }
- else if(header.offset.multi != 0)
- {
- (* size) = ((header.offset.multi*8)-(* offset));
- }
- else
- {
- (* size) = (fru->size - (* offset));
- }
- }
- return 0;
- }
- /* ipmi_fru_info_internal_use - print internal use info
- *
- * @intf: ipmi interface
- * @id: fru id
- *
- * returns -1 on error
- * returns 0 if successful
- * returns 1 if device not present
- */
- static int
- ipmi_fru_info_internal_use(struct ipmi_intf * intf, uint8_t id)
- {
- struct fru_info fru;
- uint16_t size;
- uint16_t offset;
- int rc = 0;
- rc = ipmi_fru_get_internal_use_info(intf, id, &fru, &size, &offset);
- if(rc == 0)
- {
- lprintf(LOG_DEBUG, "Internal Use Area Offset: %i", offset);
- printf( "Internal Use Area Size : %i\n", size);
- }
- else
- {
- lprintf(LOG_ERR, "Cannot access internal use area");
- return -1;
- }
- return 0;
- }
- /* ipmi_fru_help - print help text for FRU subcommand
- *
- * returns void
- */
- void
- ipmi_fru_help()
- {
- lprintf(LOG_NOTICE,
- "FRU Commands: print read write upgEkey edit internaluse get");
- } /* ipmi_fru_help() */
- /* ipmi_fru_read_internal_use - print internal use are in hex or file
- *
- * @intf: ipmi interface
- * @id: fru id
- *
- * returns -1 on error
- * returns 0 if successful
- * returns 1 if device not present
- */
- static int
- ipmi_fru_read_internal_use(struct ipmi_intf * intf, uint8_t id, char * pFileName)
- {
- struct fru_info fru;
- uint16_t size;
- uint16_t offset;
- int rc = 0;
- rc = ipmi_fru_get_internal_use_info(intf, id, &fru, &size, &offset);
- if(rc == 0)
- {
- uint8_t * frubuf;
- lprintf(LOG_DEBUG, "Internal Use Area Offset: %i", offset);
- printf( "Internal Use Area Size : %i\n", size);
- frubuf = malloc( size );
- if(frubuf)
- {
- rc = read_fru_area_section(intf, &fru, id, offset, size, frubuf);
- if(rc == 0)
- {
- if(pFileName == NULL)
- {
- uint16_t counter;
- for(counter = 0; counter < size; counter ++)
- {
- if((counter % 16) == 0)
- printf("\n%02i- ", (counter / 16));
- printf("%02X ", frubuf[counter]);
- }
- }
- else
- {
- FILE * pFile;
- pFile = fopen(pFileName,"wb");
- if (pFile)
- {
- fwrite(frubuf, size, 1, pFile);
- printf("Done\n");
- }
- else
- {
- lprintf(LOG_ERR, "Error opening file %s\n", pFileName);
- free(frubuf);
- frubuf = NULL;
- return -1;
- }
- fclose(pFile);
- }
- }
- printf("\n");
- free(frubuf);
- frubuf = NULL;
- }
- }
- else
- {
- lprintf(LOG_ERR, "Cannot access internal use area");
- }
- return 0;
- }
- /* ipmi_fru_write_internal_use - print internal use are in hex or file
- *
- * @intf: ipmi interface
- * @id: fru id
- *
- * returns -1 on error
- * returns 0 if successful
- * returns 1 if device not present
- */
- static int
- ipmi_fru_write_internal_use(struct ipmi_intf * intf, uint8_t id, char * pFileName)
- {
- struct fru_info fru;
- uint16_t size;
- uint16_t offset;
- int rc = 0;
- rc = ipmi_fru_get_internal_use_info(intf, id, &fru, &size, &offset);
- if(rc == 0)
- {
- uint8_t * frubuf;
- FILE * fp;
- uint32_t fileLength = 0;
- lprintf(LOG_DEBUG, "Internal Use Area Offset: %i", offset);
- printf( "Internal Use Area Size : %i\n", size);
- fp = fopen(pFileName, "r");
- if(fp)
- {
- /* Retreive file length, check if it's fits the Eeprom Size */
- fseek(fp, 0 ,SEEK_END);
- fileLength = ftell(fp);
- lprintf(LOG_ERR, "File Size: %i", fileLength);
- lprintf(LOG_ERR, "Area Size: %i", size);
- if(fileLength != size)
- {
- lprintf(LOG_ERR, "File size does not fit Eeprom Size");
- fclose(fp);
- fp = NULL;
- }
- else
- {
- fseek(fp, 0 ,SEEK_SET);
- }
- }
- if(fp)
- {
- frubuf = malloc( size );
- if(frubuf)
- {
- uint16_t fru_read_size;
- fru_read_size = fread(frubuf, 1, size, fp);
- if(fru_read_size == size)
- {
- rc = write_fru_area(intf, &fru, id, 0, offset, size, frubuf);
- if(rc == 0)
- {
- lprintf(LOG_INFO, "Done\n");
- }
- }
- else
- {
- lprintf(LOG_ERR, "Unable to read file: %i\n", fru_read_size);
- }
- free(frubuf);
- frubuf = NULL;
- }
- fclose(fp);
- fp = NULL;
- }
- }
- else
- {
- lprintf(LOG_ERR, "Cannot access internal use area");
- }
- return 0;
- }
- int
- ipmi_fru_main(struct ipmi_intf * intf, int argc, char ** argv)
- {
- int rc = 0;
- uint8_t fru_id = 0;
- if (argc < 1) {
- rc = ipmi_fru_print_all(intf);
- }
- else if (strncmp(argv[0], "help", 4) == 0) {
- ipmi_fru_help();
- return 0;
- }
- else if (strncmp(argv[0], "print", 5) == 0 ||
- strncmp(argv[0], "list", 4) == 0) {
- if (argc > 1) {
- if (strcmp(argv[1], "help") == 0) {
- lprintf(LOG_NOTICE, "fru print [fru id] - print information about FRU(s)");
- return 0;
- }
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- rc = __ipmi_fru_print(intf, fru_id);
- } else {
- rc = ipmi_fru_print_all(intf);
- }
- }
- else if (!strncmp(argv[0], "read", 5)) {
- if (argc > 1 && strcmp(argv[1], "help") == 0) {
- ipmi_fru_read_help();
- return 0;
- } else if (argc < 3) {
- lprintf(LOG_ERR, "Not enough parameters given.");
- ipmi_fru_read_help();
- return (-1);
- }
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- /* There is a file name in the parameters */
- if (is_valid_filename(argv[2]) != 0)
- return (-1);
- if (verbose) {
- printf("FRU ID : %d\n", fru_id);
- printf("FRU File : %s\n", argv[2]);
- }
- /* TODO - rc is missing */
- ipmi_fru_read_to_bin(intf, argv[2], fru_id);
- }
- else if (!strncmp(argv[0], "write", 5)) {
- if (argc > 1 && strcmp(argv[1], "help") == 0) {
- ipmi_fru_write_help();
- return 0;
- } else if (argc < 3) {
- lprintf(LOG_ERR, "Not enough parameters given.");
- ipmi_fru_write_help();
- return (-1);
- }
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- /* There is a file name in the parameters */
- if (is_valid_filename(argv[2]) != 0)
- return (-1);
- if (verbose) {
- printf("FRU ID : %d\n", fru_id);
- printf("FRU File : %s\n", argv[2]);
- }
- /* TODO - rc is missing */
- ipmi_fru_write_from_bin(intf, argv[2], fru_id);
- }
- else if (!strncmp(argv[0], "upgEkey", 7)) {
- if (argc > 1 && strcmp(argv[1], "help") == 0) {
- ipmi_fru_upgekey_help();
- return 0;
- } else if (argc < 3) {
- lprintf(LOG_ERR, "Not enough parameters given.");
- ipmi_fru_upgekey_help();
- return (-1);
- }
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- /* There is a file name in the parameters */
- if (is_valid_filename(argv[2]) != 0)
- return (-1);
- rc = ipmi_fru_upg_ekeying(intf, argv[2], fru_id);
- }
- else if (!strncmp(argv[0], "internaluse", 11)) {
- if (argc > 1 && strcmp(argv[1], "help") == 0) {
- ipmi_fru_internaluse_help();
- return 0;
- }
- if ( (argc >= 3) && (!strncmp(argv[2], "info", 4)) ) {
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- rc = ipmi_fru_info_internal_use(intf, fru_id);
- }
- else if ( (argc >= 3) && (!strncmp(argv[2], "print", 5)) ) {
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- rc = ipmi_fru_read_internal_use(intf, fru_id, NULL);
- }
- else if ( (argc >= 4) && (!strncmp(argv[2], "read", 4)) ) {
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- /* There is a file name in the parameters */
- if (is_valid_filename(argv[3]) != 0)
- return (-1);
- lprintf(LOG_DEBUG, "FRU ID : %d", fru_id);
- lprintf(LOG_DEBUG, "FRU File : %s", argv[3]);
- rc = ipmi_fru_read_internal_use(intf, fru_id, argv[3]);
- }
- else if ( (argc >= 4) && (!strncmp(argv[2], "write", 5)) ) {
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- /* There is a file name in the parameters */
- if (is_valid_filename(argv[3]) != 0)
- return (-1);
- lprintf(LOG_DEBUG, "FRU ID : %d", fru_id);
- lprintf(LOG_DEBUG, "FRU File : %s", argv[3]);
- rc = ipmi_fru_write_internal_use(intf, fru_id, argv[3]);
- } else {
- lprintf(LOG_ERR,
- "Either unknown command or not enough parameters given.");
- ipmi_fru_internaluse_help();
- return (-1);
- }
- }
- else if (!strncmp(argv[0], "edit", 4)) {
- if (argc > 1 && strcmp(argv[1], "help") == 0) {
- ipmi_fru_edit_help();
- return 0;
- } else if (argc < 2) {
- lprintf(LOG_ERR, "Not enough parameters given.");
- ipmi_fru_edit_help();
- return (-1);
- }
-
- if (argc >= 2) {
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- if (verbose) {
- printf("FRU ID : %d\n", fru_id);
- }
- } else {
- printf("Using default FRU ID: %d\n", fru_id);
- }
- if (argc >= 3) {
- if (!strncmp(argv[2], "field", 5)) {
- if (argc != 6) {
- lprintf(LOG_ERR, "Not enough parameters given.");
- ipmi_fru_edit_help();
- return (-1);
- }
- rc = ipmi_fru_set_field_string(intf, fru_id, *argv[3], *argv[4],
- (char *) argv[5]);
- } else if (!strncmp(argv[2], "oem", 3)) {
- rc = ipmi_fru_edit_multirec(intf, fru_id, argc, argv);
- } else {
- lprintf(LOG_ERR, "Invalid command: %s", argv[2]);
- ipmi_fru_edit_help();
- return (-1);
- }
- } else {
- rc = ipmi_fru_edit_multirec(intf, fru_id, argc, argv);
- }
- }
- else if (!strncmp(argv[0], "get", 4)) {
- if (argc > 1 && (strncmp(argv[1], "help", 4) == 0)) {
- ipmi_fru_get_help();
- return 0;
- } else if (argc < 2) {
- lprintf(LOG_ERR, "Not enough parameters given.");
- ipmi_fru_get_help();
- return (-1);
- }
- if (argc >= 2) {
- if (is_fru_id(argv[1], &fru_id) != 0)
- return (-1);
- if (verbose) {
- printf("FRU ID : %d\n", fru_id);
- }
- } else {
- printf("Using default FRU ID: %d\n", fru_id);
- }
- if (argc >= 3) {
- if (!strncmp(argv[2], "oem", 3)) {
- rc = ipmi_fru_get_multirec(intf, fru_id, argc, argv);
- } else {
- lprintf(LOG_ERR, "Invalid command: %s", argv[2]);
- ipmi_fru_get_help();
- return (-1);
- }
- } else {
- rc = ipmi_fru_get_multirec(intf, fru_id, argc, argv);
- }
- }
- else {
- lprintf(LOG_ERR, "Invalid FRU command: %s", argv[0]);
- ipmi_fru_help();
- return (-1);
- }
- return rc;
- }
- /* ipmi_fru_set_field_string - Set a field string to a new value, Need to be the same size. If
- * size if not equal, the function ipmi_fru_set_field_string_rebuild
- * will be called.
- *
- * @intf: ipmi interface
- * @id: fru id
- * @f_type: Type of the Field : c=Chassis b=Board p=Product
- * @f_index: findex of the field, zero indexed.
- * @f_string: NULL terminated string
- *
- * returns -1 on error
- * returns 1 if successful
- */
- static int
- ipmi_fru_set_field_string(struct ipmi_intf * intf, uint8_t fruId, uint8_t
- f_type, uint8_t f_index, char *f_string)
- {
- struct ipmi_rs *rsp;
- struct ipmi_rq req;
- struct fru_info fru;
- struct fru_header header;
- uint8_t msg_data[4];
- uint8_t checksum;
- int i = 0;
- int rc = 1;
- uint8_t *fru_data = NULL;
- uint8_t *fru_area = NULL;
- uint32_t fru_field_offset, fru_field_offset_tmp;
- uint32_t fru_section_len, header_offset;
- memset(msg_data, 0, 4);
- msg_data[0] = fruId;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_INFO;
- req.msg.data = msg_data;
- req.msg.data_len = 1;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- printf(" Device not present (No Response)\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- if (rsp->ccode > 0) {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- memset(&fru, 0, sizeof(fru));
- fru.size = (rsp->data[1] << 8) | rsp->data[0];
- fru.access = rsp->data[2] & 0x1;
- if (fru.size < 1) {
- printf(" Invalid FRU size %d", fru.size);
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- /*
- * retrieve the FRU header
- */
- msg_data[0] = fruId;
- msg_data[1] = 0;
- msg_data[2] = 0;
- msg_data[3] = 8;
- memset(&req, 0, sizeof(req));
- req.msg.netfn = IPMI_NETFN_STORAGE;
- req.msg.cmd = GET_FRU_DATA;
- req.msg.data = msg_data;
- req.msg.data_len = 4;
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL)
- {
- printf(" Device not present (No Response)\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- if (rsp->ccode > 0)
- {
- printf(" Device not present (%s)\n",
- val2str(rsp->ccode, completion_code_vals));
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- if (verbose > 1)
- printbuf(rsp->data, rsp->data_len, "FRU DATA");
- memcpy(&header, rsp->data + 1, 8);
- if (header.version != 1)
- {
- printf(" Unknown FRU header version 0x%02x",
- header.version);
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- fru_data = malloc( fru.size );
- if( fru_data == NULL )
- {
- printf("Out of memory!\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- /* Setup offset from the field type */
- /* Chassis type field */
- if (f_type == 'c' ) {
- header_offset = (header.offset.chassis * 8);
- read_fru_area(intf ,&fru, fruId, header_offset , 3 , fru_data);
- fru_field_offset = 3;
- fru_section_len = *(fru_data + 1) * 8;
- }
- /* Board type field */
- else if (f_type == 'b' ) {
- header_offset = (header.offset.board * 8);
- read_fru_area(intf ,&fru, fruId, header_offset , 3 , fru_data);
- fru_field_offset = 6;
- fru_section_len = *(fru_data + 1) * 8;
- }
- /* Product type field */
- else if (f_type == 'p' ) {
- header_offset = (header.offset.product * 8);
- read_fru_area(intf ,&fru, fruId, header_offset , 3 , fru_data);
- fru_field_offset = 3;
- fru_section_len = *(fru_data + 1) * 8;
- }
- else
- {
- printf("Wrong field type.");
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- memset(fru_data, 0, fru.size);
- if( read_fru_area(intf ,&fru, fruId, header_offset ,
- fru_section_len , fru_data) < 0 )
- {
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- /* Convert index from character to decimal */
- f_index= f_index - 0x30;
- /*Seek to field index */
- for (i=0; i <= f_index; i++) {
- fru_field_offset_tmp = fru_field_offset;
- if (fru_area != NULL) {
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = (uint8_t *) get_fru_area_str(fru_data, &fru_field_offset);
- }
- if( (fru_area == NULL ) || strlen((const char *)fru_area) == 0 ) {
- printf("Field not found !\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- if ( strlen((const char *)fru_area) == strlen((const char *)f_string) )
- {
- printf("Updating Field '%s' with '%s' ...\n", fru_area, f_string );
- memcpy(fru_data + fru_field_offset_tmp + 1,
- f_string, strlen(f_string));
- checksum = 0;
- /* Calculate Header Checksum */
- for (i = 0; i < fru_section_len - 1; i++)
- {
- checksum += fru_data[i];
- }
- checksum = (~checksum) + 1;
- fru_data[fru_section_len - 1] = checksum;
- /* Write the updated section to the FRU data; source offset => 0 */
- if( write_fru_area(intf, &fru, fruId, 0,
- header_offset, fru_section_len, fru_data) < 0 )
- {
- printf("Write to FRU data failed.\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- }
- else {
- printf("String size are not equal, resizing fru to fit new string\n");
- if(
- ipmi_fru_set_field_string_rebuild(intf,fruId,fru,header,f_type,f_index,f_string)
- )
- {
- rc = (-1);
- goto ipmi_fru_set_field_string_out;
- }
- }
- ipmi_fru_set_field_string_out:
- if (fru_data != NULL) {
- free(fru_data);
- fru_data = NULL;
- }
- if (fru_area != NULL) {
- free(fru_area);
- fru_area = NULL;
- }
- return rc;
- }
- /*
- This function can update a string within of the following section when the size is not equal:
- Chassis
- Product
- Board
- */
- /* ipmi_fru_set_field_string_rebuild - Set a field string to a new value, When size are not
- * the same size.
- *
- * This function can update a string within of the following section when the size is not equal:
- *
- * - Chassis
- * - Product
- * - Board
- *
- * @intf: ipmi interface
- * @fruId: fru id
- * @fru: info about fru
- * @header: contain the header of the FRU
- * @f_type: Type of the Field : c=Chassis b=Board p=Product
- * @f_index: findex of the field, zero indexed.
- * @f_string: NULL terminated string
- *
- * returns -1 on error
- * returns 1 if successful
- */
- #define DBG_RESIZE_FRU
- static int
- ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
- struct fru_info fru, struct fru_header header,
- uint8_t f_type, uint8_t f_index, char *f_string)
- {
- int i = 0;
- uint8_t *fru_data_old = NULL;
- uint8_t *fru_data_new = NULL;
- uint8_t *fru_area = NULL;
- uint32_t fru_field_offset, fru_field_offset_tmp;
- uint32_t fru_section_len, header_offset;
- uint32_t chassis_offset, board_offset, product_offset;
- uint32_t chassis_len, board_len, product_len, product_len_new;
- int num_byte_change = 0, padding_len = 0;
- uint32_t counter;
- unsigned char cksum;
- int rc = 1;
- fru_data_old = calloc( fru.size, sizeof(uint8_t) );
- fru_data_new = malloc( fru.size );
- if( fru_data_old == NULL || fru_data_new == NULL )
- {
- printf("Out of memory!\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_rebuild_out;
- }
- /*************************
- 1) Read ALL FRU */
- printf("Read All FRU area\n");
- printf("Fru Size : %u bytes\n", fru.size);
- /* Read current fru data */
- read_fru_area(intf ,&fru, fruId, 0, fru.size , fru_data_old);
- #ifdef DBG_RESIZE_FRU
- printf("Copy to new FRU\n");
- #endif
- /*************************
- 2) Copy all FRU to new FRU */
- memcpy(fru_data_new, fru_data_old, fru.size);
- /* Build location of all modifiable components */
- chassis_offset = (header.offset.chassis * 8);
- board_offset = (header.offset.board * 8);
- product_offset = (header.offset.product * 8);
- /* Retrieve length of all modifiable components */
- chassis_len = *(fru_data_old + chassis_offset + 1) * 8;
- board_len = *(fru_data_old + board_offset + 1) * 8;
- product_len = *(fru_data_old + product_offset + 1) * 8;
- product_len_new = product_len;
- /* Chassis type field */
- if (f_type == 'c' )
- {
- header_offset = chassis_offset;
- fru_field_offset = chassis_offset + 3;
- fru_section_len = chassis_len;
- }
- /* Board type field */
- else if (f_type == 'b' )
- {
- header_offset = board_offset;
- fru_field_offset = board_offset + 6;
- fru_section_len = board_len;
- }
- /* Product type field */
- else if (f_type == 'p' )
- {
- header_offset = product_offset;
- fru_field_offset = product_offset + 3;
- fru_section_len = product_len;
- }
- else
- {
- printf("Wrong field type.");
- rc = (-1);
- goto ipmi_fru_set_field_string_rebuild_out;
- }
- /*************************
- 3) Seek to field index */
- for (i = 0;i <= f_index; i++) {
- fru_field_offset_tmp = fru_field_offset;
- if (fru_area != NULL) {
- free(fru_area);
- fru_area = NULL;
- }
- fru_area = (uint8_t *) get_fru_area_str(fru_data_old, &fru_field_offset);
- }
- if( (fru_area == NULL ) || strlen((const char *)fru_area) == 0 ) {
- printf("Field not found (1)!\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_rebuild_out;
- }
- #ifdef DBG_RESIZE_FRU
- printf("Section Length: %u\n", fru_section_len);
- #endif
- /*************************
- 4) Check number of padding bytes and bytes changed */
- for(counter = 2; counter < fru_section_len; counter ++)
- {
- if(*(fru_data_old + (header_offset + fru_section_len - counter)) == 0)
- padding_len ++;
- else
- break;
- }
- num_byte_change = strlen(f_string) - strlen(fru_area);
- #ifdef DBG_RESIZE_FRU
- printf("Padding Length: %u\n", padding_len);
- printf("NumByte Change: %i\n", num_byte_change);
- printf("Start SecChnge: %x\n", *(fru_data_old + fru_field_offset_tmp));
- printf("End SecChnge : %x\n", *(fru_data_old + fru_field_offset_tmp + strlen(f_string) + 1));
- printf("Start Section : %x\n", *(fru_data_old + header_offset));
- printf("End Sec wo Pad: %x\n", *(fru_data_old + header_offset + fru_section_len - 2 - padding_len));
- printf("End Section : %x\n", *(fru_data_old + header_offset + fru_section_len - 1));
- #endif
- /* Calculate New Padding Length */
- padding_len -= num_byte_change;
- #ifdef DBG_RESIZE_FRU
- printf("New Padding Length: %i\n", padding_len);
- #endif
- /*************************
- 5) Check if section must be resize. This occur when padding length is not between 0 and 7 */
- if( (padding_len < 0) || (padding_len >= 8))
- {
- uint32_t remaining_offset = ((header.offset.product * 8) + product_len);
- int change_size_by_8;
- if(padding_len >= 8)
- {
- /* Section must be set smaller */
- change_size_by_8 = ((padding_len) / 8) * (-1);
- }
- else
- {
- /* Section must be set bigger */
- change_size_by_8 = 1 + (((padding_len+1) / 8) * (-1));
- }
- /* Recalculate padding and section length base on the section changes */
- fru_section_len += (change_size_by_8 * 8);
- padding_len += (change_size_by_8 * 8);
- #ifdef DBG_RESIZE_FRU
- printf("change_size_by_8: %i\n", change_size_by_8);
- printf("New Padding Length: %i\n", padding_len);
- printf("change_size_by_8: %i\n", change_size_by_8);
- printf("header.offset.board: %i\n", header.offset.board);
- #endif
- /* Must move sections */
- /* Section that can be modified are as follow
- Chassis
- Board
- product */
- /* Chassis type field */
- if (f_type == 'c' )
- {
- printf("Moving Section Chassis, from %i to %i\n",
- ((header.offset.board) * 8),
- ((header.offset.board + change_size_by_8) * 8)
- );
- memcpy(
- (fru_data_new + ((header.offset.board + change_size_by_8) * 8)),
- (fru_data_old + (header.offset.board) * 8),
- board_len
- );
- header.offset.board += change_size_by_8;
- }
- /* Board type field */
- if ((f_type == 'c' ) || (f_type == 'b' ))
- {
- printf("Moving Section Product, from %i to %i\n",
- ((header.offset.product) * 8),
- ((header.offset.product + change_size_by_8) * 8)
- );
- memcpy(
- (fru_data_new + ((header.offset.product + change_size_by_8) * 8)),
- (fru_data_old + (header.offset.product) * 8),
- product_len
- );
- header.offset.product += change_size_by_8;
- }
- if ((f_type == 'c' ) || (f_type == 'b' ) || (f_type == 'p' )) {
- printf("Change multi offset from %d to %d\n", header.offset.multi, header.offset.multi + change_size_by_8);
- header.offset.multi += change_size_by_8;
- }
- /* Adjust length of the section */
- if (f_type == 'c')
- {
- *(fru_data_new + chassis_offset + 1) += change_size_by_8;
- }
- else if( f_type == 'b')
- {
- *(fru_data_new + board_offset + 1) += change_size_by_8;
- }
- else if( f_type == 'p')
- {
- *(fru_data_new + product_offset + 1) += change_size_by_8;
- product_len_new = *(fru_data_new + product_offset + 1) * 8;
- }
- /* Rebuild Header checksum */
- {
- unsigned char * pfru_header = (unsigned char *) &header;
- header.checksum = 0;
- for(counter = 0; counter < (sizeof(struct fru_header) -1); counter ++)
- {
- header.checksum += pfru_header[counter];
- }
- header.checksum = (0 - header.checksum);
- memcpy(fru_data_new, pfru_header, sizeof(struct fru_header));
- }
- /* Move remaining sections in 1 copy */
- printf("Moving Remaining Bytes (Multi-Rec , etc..), from %i to %i\n",
- remaining_offset,
- ((header.offset.product) * 8) + product_len_new
- );
- if(((header.offset.product * 8) + product_len_new - remaining_offset) < 0)
- {
- memcpy(
- fru_data_new + (header.offset.product * 8) + product_len_new,
- fru_data_old + remaining_offset,
- fru.size - remaining_offset
- );
- }
- else
- {
- memcpy(
- fru_data_new + (header.offset.product * 8) + product_len_new,
- fru_data_old + remaining_offset,
- fru.size - ((header.offset.product * 8) + product_len_new)
- );
- }
- }
- /* Update only if it's fits padding length as defined in the spec, otherwise, it's an internal
- error */
- /*************************
- 6) Update Field and sections */
- if( (padding_len >=0) && (padding_len < 8))
- {
- /* Do not requires any change in other section */
- /* Change field length */
- printf(
- "Updating Field : '%s' with '%s' ... (Length from '%d' to '%d')\n",
- fru_area, f_string,
- (int)*(fru_data_old + fru_field_offset_tmp),
- (int)(0xc0 + strlen(f_string)));
- *(fru_data_new + fru_field_offset_tmp) = (0xc0 + strlen(f_string));
- memcpy(fru_data_new + fru_field_offset_tmp + 1, f_string, strlen(f_string));
- /* Copy remaing bytes in section */
- #ifdef DBG_RESIZE_FRU
- printf("Copying remaining of sections: %d \n",
- (int)((fru_data_old + header_offset + fru_section_len - 1) -
- (fru_data_old + fru_field_offset_tmp + strlen(f_string) + 1)));
- #endif
- memcpy((fru_data_new + fru_field_offset_tmp + 1 +
- strlen(f_string)),
- (fru_data_old + fru_field_offset_tmp + 1 +
- strlen(fru_area)),
- ((fru_data_old + header_offset + fru_section_len - 1) -
- (fru_data_old + fru_field_offset_tmp + strlen(f_string) + 1)));
- /* Add Padding if required */
- for(counter = 0; counter < padding_len; counter ++)
- {
- *(fru_data_new + header_offset + fru_section_len - 1 -
- padding_len + counter) = 0;
- }
- /* Calculate New Checksum */
- cksum = 0;
- for( counter = 0; counter <fru_section_len-1; counter ++ )
- {
- cksum += *(fru_data_new + header_offset + counter);
- }
- *(fru_data_new + header_offset + fru_section_len - 1) = (0 - cksum);
- #ifdef DBG_RESIZE_FRU
- printf("Calculate New Checksum: %x\n", (0 - cksum));
- #endif
- }
- else
- {
- printf( "Internal error, padding length %i (must be from 0 to 7) ", padding_len );
- rc = (-1);
- goto ipmi_fru_set_field_string_rebuild_out;
- }
- /*************************
- 7) Finally, write new FRU */
- printf("Writing new FRU.\n");
- if( write_fru_area( intf, &fru, fruId, 0, 0, fru.size, fru_data_new ) < 0 )
- {
- printf("Write to FRU data failed.\n");
- rc = (-1);
- goto ipmi_fru_set_field_string_rebuild_out;
- }
- printf("Done.\n");
- ipmi_fru_set_field_string_rebuild_out:
- if (fru_area != NULL) {
- free(fru_area);
- fru_area = NULL;
- }
- if (fru_data_new != NULL) {
- free(fru_data_new);
- fru_data_new = NULL;
- }
- if (fru_data_old != NULL) {
- free(fru_data_old);
- fru_data_old = NULL;
- }
- return rc;
- }
|