Няшная / Говнокод #20200 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
int hardinfo_updata( struct UPINFO * headinfo, struct HARDINFO * hardinfo )
{
	char sbuf[128] ;
	int sn_len = 0 ;
	char *psn ;
	
	printf("%s\n",__FUNCTION__  ) ;
	memset( sbuf, 0xFF, 128 ) ;
	if( strcmp( hardinfo->flag, "hardinfo") != 0 )
	{
		psn = (char *)hardinfo ;
		sn_len = *psn ;
		psn += 1;
		memcpy( sbuf, psn , 127 ) ;
	}
	else
	{
		sn_len = hardinfo->sn_len ;
		memcpy(sbuf, hardinfo->sn, 128 ) ;
	}

	memcpy( hardinfo, &(headinfo->hardinfo), sizeof( struct HARDINFO ) ) ;
	hardinfo->sn_len = sn_len ;
	if( hardinfo->sn_len > 128 ) hardinfo->sn_len = 128 ;
	memcpy( hardinfo->sn, sbuf, hardinfo->sn_len ) ;
	
	memset( 0x30008000, 0xFF, 0x20000 ) ;
	memcpy( 0x30008000, hardinfo, sizeof( struct HARDINFO ) ) ;
	memset( sbuf, 0xFF, 128 ) ;
	sprintf( sbuf, "%s %x %x\0", "nand erase 80000 80000 ;nand write 0x30008000", 0x80000, 0x20000) ;
	run_command( sbuf,0);

	memset( sbuf, 0, 128 ) ;
	sprintf( sbuf, "%s %x\0", "nand read  0x31000000 80000 ", 0x20000 ) ;
	run_command(sbuf, 0 ) ;

	if( memcmp( 0x30008000, 0x31000000, sizeof( struct HARDINFO) ) != 0 )
	{
		printf("bootloader data crc error\n") ;
		return 0 ;
	}
	else
	{
		printf("update hardinfo is ok\n") ;
	}

	return 1 ;
}

CRC через memcpy. Из пропатченного китайцами u-boot

Запостил: j123123 j123123, (Updated )

Комментарии (65) RSS

  • блин, опять memcpy и memcmp спутал(в описании к говнокоду). Не выспался еще. Жаль что описание поправить нельзя
    Ответить
  • Как же бесит объявление переменных в начале большой функции...

    Вот у меня сразу в мозгу триггернулось: "ага, в верхней ветке psn заполнили, а в нижней - нет, если внизу её заюзают - всё распидорасит... а, не юзают, ну и слава богу".
    Ответить
      • Уже C11 давно прижился, а вы всё ещё по 99 страдаете.
        Ответить
      • Да даже c89 позволял описывать переменные в начале блока...
        Ответить
      • C99 вечен и непорочен. Ты умрешь, и прах твой развеется по ветру, а на C99 и дальше будут писать царский код
        Ответить
        • потому что проекты начали в 99-м и переписывать всё с нуля лень?
          Ответить
    • >>Как же бесит объявление переменных в начале большой функции...
      а мне нравится)

      сразу представляю себя таким юникс хакером за PDP в больших очках, клечатой рубашке и с бородой
      Ответить
  • Ну верификация через memcmp тут как раз одно из самых адекватных мест, к которому особо не доебёшься...
    // мы стираем флешку, поэтому буфер под null-terminated строку с
    // командой надо обязательно заполнить 0xFF...
    memset(sbuf, 0xFF, 128);
    sprintf(sbuf, "%s %x %x\0", "nand erase 80000 80000 ;nand write 0x30008000", 0x80000, 0x20000);
    Ответить
    • А нет ли опасений по поводу того, что после memset/memcpy у проца может быть кэшнута та память, и когда делаем memcmp то сравниваться будет не та память, которая на NAND флеше, а которая в кэше проца?
      Ответить
      • Ну будем надеяться, что 0x30000000 - uncachable зона.

        Ну а если кешируется, и мы там можем увидеть кусок старых данных от старой прошивки - ну тут только какой-то системнозависимой инструкцией кеш прочищать... memcmp не виноватый, тут совершенно любая проверка обосрётся.
        Ответить
        • >memcmp не виноватый, тут совершенно любая проверка обосрётся.

          Ну если сделать нечто вроде
          writeflash(buf1, addr, 128);
          readflash(buf2, addr, 128);
          memcmp(buf1, buf2, 128);

          То все должно пройти гладко. Вообще, я не особо курил код этого u-boot, может таких извратов делать не надо
          Ответить
          • > Ну если сделать нечто вроде
            Ну здесь же именно так и делают 🙂

            З.Ы run_command() это чё-то типа system()?
            Ответить
            • Это когда ты подцепляешься через UART к устройству, то там консолечка, ты вводишь всякие команды, и эти команды обрабатывает этот самый run_command
              Ответить
      • З.Ы. А, да тут же к самому NAND'у никто не лезет. Просто просят какую-то внешнюю тулзу записать туда байтики с адреса 0x30008000 и прочитать их на адрес 0x31000000. Тогда вообще всё ок.
        Ответить
        • Если интересно порыться в этом г-не, могу скинуть исходники бутлодера, они не секретные
          Ответить
            • да. ты угадал. в у-бууте есть комманды, и этот кусок кода ими пользуется.

              так как у-буут стартует рано, и как правило архитектура известна, то и лэйаут памяти тоже известен - почему в у-бууте использование фиксированых хардкоженых адресов памяти (0x30008000, 0x31000000) и популярно.

              код на самом деле не так плох. учитывая что писали хардварщики - так почти идеал. и сообщение об ошибке и не так плохо: можно было бы "consistency check" написать - но типичные пользователи уже знают CRC ошибки, и просто не имеет смысл их грузить деталями. в конце концов, CRC это дешевая имитация memcmp().
              Ответить
      • Ну хер их знает, вдруг там у них run_command() может исполнять несколько команд, разделённых нулями...

        Ты лучше объясни, зачем там memset на 0xFF
        Ответить
        • Скорее тут причина в том, что это написано криворукими китайцами
          Ответить
        • Могу только судить по своему опыту с МПЕГ2-ТС.

          Иногда тупо выгодней сделать
          memset(payload, 0xFF, 184);

          и потом заполнить payload, чем
          /* payload goes here */
          while (i < 184) payload[i++] = 0xFF;


          Особенно если payload состоит из 20 байт, ибо по Стандарту, unused bytes shall be set to 0xFF.
          Ответить
          • Но нахуй добивать командную строку 0xFF'ками? :3

            З.Ы. Я понимаю, зачем это делается с бинарными данными.
            Ответить
        • > Ты лучше объясни, зачем там memset на 0xFF

          может копипаситили memset из другого места в коде. некоторые флеши перед программированием надо в 0xFF ставить.
          Ответить
          • > memset( 0x30008000, 0xFF, 0x20000 ) ;
            Видимо вот отсюда пробралось.
            Ответить
          • > перед программированием надо в 0xFF ставить
            Ну скорее просто чтобы не дрочить хвост флешки лишними переключениями 1 -> 0. 0xFF один хер получается только после отдельной команды стирания...
            Ответить
            • насколько я понял (в зависимости от типа шлеша?) у них 1ые биты это просто нормальное состояние флеша, а 0 нужно записывать. но это просто спекуляция, на основании разговоров с хардварщиками. (NOR & NAND - этот NOT в начале означает отрицание и то что единички флешу представлять не надо, а только нолики.)
              Ответить
              • Да, там, емнип, 1 - нет заряда на кондёре, 0 - есть заряд. Отсюда и N.

                А NOR/NAND - как соединены между собой ячейки. В NOR параллельно (wired-or) и можно любой бит зарядить независимо, но плотность хуёвая, получаются от силы мегабайты. В NAND'е - последовательно (wired-and), поэтому можно записать только всю цепочку разом (единички маскируются, нолики заряжаются), зато лишнего обвеса минимум, можно делать гигабайтные флехи.

                А выкачивается заряд (забиваются единички) в обоих типах только большими блоками...
                Ответить
        • >Ну хер их знает, вдруг там у них run_command() может исполнять несколько команд, разделённых нулями...

          Даже если и так, sprintf не будет разбирать строку дальше нуля. Китайцы вероятно решили, что чтобы в буфер попал ноль в конце, надо обязательно "\0" добавить в конце строки скармливаемой этому sprintf, а иначе там сразу после текста полезут эти 0xFF
          Ответить
      • А почему тебя не смущает то, что sprinf там вообще нахрен не нужен? Вот это например
        sprintf( sbuf, "%s %x %x\0", "nand erase 80000 80000 ;nand write 0x30008000", 0x80000, 0x20000) ;

        элементарно заменяется на:
        strcpy(sbuf, "nand erase 80000 80000 ;nand write 0x30008000 0x80000 0x20000");
        Ответить
        • Не, я бы всё-таки sprintf поюзал, чтобы константам имена дать.
          Ответить
          • А еще лучше вызывать те функции, которые этот самый run_command вызывает в ответ на эту говностроку. Но китайцам лень в этой хуйне разбираться, лучше в строку воткнем хуйни и скормим в run_command()
            Ответить
            • Ну там не факт, что они доступны откуда надо и т.п... Но в идеале - да.
              Ответить
              • все там доступно, это загрузчик, а не какая-то там ОС
                Ответить
                • Ну это ж static стирать, в хедер прототип выносить и т.п...
                  Ответить
        • может быть планировали в будущем 0x80000 и 0x20000 из переменных окружения брать. sprintf() не мешает.
          Ответить
  • > char sbuf[128] ;
    > char sbuf[заранее_угадай] ;

    Как я сука ненавижу сишколибу для строк
    Ответить

Добавить комментарий

Переведи на "PHP", guest!

    А не использовать ли нам bbcode?


    8